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`))
Gud Boi 2026-08-21 23:19:49 -04:00
parent d6d4de8c6f
commit 5b4dfac07e
4 changed files with 127 additions and 33 deletions

View File

@ -33,6 +33,11 @@ uv run --frozen --no-sync pytest --collect-only -q tests/
Collection is not a mandatory precursor to every narrow run. Ask before Collection is not a mandatory precursor to every narrow run. Ask before
provisioning or changing an environment. provisioning or changing an environment.
Before trusting CLI-selected runtime settings, inspect
`TRACTOR_SPAWN_METHOD` and `TRACTOR_LOGLEVEL`. They override the spawn method
and runtime log level passed by callers, so report active values with test
results rather than claiming the CLI flags alone selected the runtime.
## Pytest Configuration And Commands ## Pytest Configuration And Commands
`pyproject.toml` configures: `pyproject.toml` configures:
@ -64,7 +69,8 @@ uv run --frozen --no-sync pytest tests/ -k 'cancel and not slow'
uv run --frozen --no-sync pytest --lf uv run --frozen --no-sync pytest --lf
``` ```
A current CI-equivalent TCP row is: After verifying that the no-sync environment is current, these pytest
arguments match the Linux TCP CI row:
```text ```text
CI=1 uv run --frozen --no-sync pytest tests/ -rsx --spawn-backend=trio --tpt-proto=tcp --capture=fd CI=1 uv run --frozen --no-sync pytest tests/ -rsx --spawn-backend=trio --tpt-proto=tcp --capture=fd
@ -81,6 +87,7 @@ Supported spawn backends:
Do not advertise `subint`, `subint_forkserver`, or Do not advertise `subint`, `subint_forkserver`, or
`main_thread_forkserver` as runnable backends. Supported transports are `main_thread_forkserver` as runnable backends. Supported transports are
`tcp` (default) and `uds`. Run one transport per pytest session. `tcp` (default) and `uds`. Run one transport per pytest session.
`mp_forkserver` and UDS are POSIX-only.
Other Tractor plugin options include: Other Tractor plugin options include:
@ -97,14 +104,15 @@ uv run --frozen --no-sync pytest tests/test_spawning.py --spawn-backend=mp_spawn
uv run --frozen --no-sync pytest tests/test_spawning.py --spawn-backend=mp_forkserver --capture=sys uv run --frozen --no-sync pytest tests/test_spawning.py --spawn-backend=mp_forkserver --capture=sys
``` ```
CI currently exercises the `trio` backend: TCP and UDS on Linux, and TCP on CI currently exercises Python 3.13 with the `trio` backend: TCP and UDS on
macOS. Linux and macOS, plus an informational TCP row on Windows whose pytest step
uses `continue-on-error`.
## Registry And Transport Isolation ## Registry And Transport Isolation
Tests requesting the `reg_addr` fixture use session-unique addresses: a Tests requesting the `reg_addr` fixture use addresses randomized per session:
randomized unprivileged loopback port for TCP or a unique socket name under an unreserved unprivileged loopback port for TCP or a unique socket name under
the platform runtime directory for UDS. the platform runtime directory for UDS. A TCP collision remains possible.
The runtime fallback remains `127.0.0.1:1616` or `registry@1616.sock`. The runtime fallback remains `127.0.0.1:1616` or `registry@1616.sock`.
Inspect that fallback only when the selected test intentionally uses runtime Inspect that fallback only when the selected test intentionally uses runtime
@ -124,9 +132,14 @@ uv run --frozen --no-sync pytest <node> -s
``` ```
Treat `-s` as a diagnostic comparison, not a pass-equivalent workaround. Do Treat `-s` as a diagnostic comparison, not a pass-equivalent workaround. Do
not add a global pytest timeout: both timeout enforcement methods can corrupt not use it to reinterpret an ordinary captured pass. Interactive `--tpdb` or
or terminate Trio sessions. Use existing Trio-aware guards and an outer job `tractor.pause()` sessions are different: they require a real TTY and disabled
timeout when necessary. capture, normally `-s`.
Do not add a global pytest timeout. `fail_after_w_trace` is Trio-cooperative;
`afk_alarm_w_trace` is a POSIX main-thread `SIGALRM` hard backstop and can
raise asynchronously. Use the latter only as a last resort, not as a generally
Trio-safe timeout replacement.
For live task-tree diagnosis: For live task-tree diagnosis:
@ -135,25 +148,41 @@ uv run --frozen --no-sync pytest <node> --enable-stackscope --capture=sys
kill -USR1 <pytest-or-subactor-pid> kill -USR1 <pytest-or-subactor-pid>
``` ```
Tests using `fail_after_w_trace` or `afk_alarm_w_trace` write snapshots under Stackscope appends dumps to `/tmp/tractor-stackscope-<pid>.log`, including when
`$XDG_CACHE_HOME/tractor/hung-dumps/` and print an end-of-session index. pytest capture hides terminal output. SIGUSR1 stackscope is unavailable on
Windows and degrades to a no-op there.
When a trace guard actually fires and snapshot capture succeeds, it writes
under `$XDG_CACHE_HOME/tractor/hung-dumps/`, falling back beneath
`~/.cache/tractor/hung-dumps/`, and prints an end-of-session index. A normal
non-timeout run creates no snapshot.
## Cleanup And `tractor-reap` ## Cleanup And `tractor-reap`
Normal pytest teardown reaps surviving pytest descendants with SIGINT, a On Linux, normal pytest teardown discovers surviving descendants through
three-second grace period, then SIGKILL, and sweeps recognized orphaned UDS `/proc`, sends SIGINT, waits three seconds, then escalates survivors to
socket files. It does not sweep shared memory and cannot run if pytest never SIGKILL. It does not sweep shared memory and cannot run if pytest never reaches
reaches fixture teardown. fixture teardown.
Process discovery is a no-op off Linux. UDS PID liveness also depends on
`/proc`; on macOS, recognized PID-named sockets can therefore be classified as
dead without proof. The session-scoped autouse fixture currently passes those
candidates directly to `reap_uds()` at teardown. Do not treat its non-Linux
classification as proof of orphanhood or run concurrent live Tractor sessions
against the same UDS bindspace.
Use the CLI in inspection-only mode first: Use the CLI in inspection-only mode first:
```text ```text
scripts/tractor-reap -n uv run --frozen --no-sync scripts/tractor-reap -n
scripts/tractor-reap --parent <pytest-pid> -n uv run --frozen --no-sync scripts/tractor-reap --parent <pytest-pid> -n
scripts/tractor-reap --shm --uds -n uv run --frozen --no-sync scripts/tractor-reap --shm --uds -n
scripts/tractor-reap --uds-only -n uv run --frozen --no-sync scripts/tractor-reap --uds-only -n
``` ```
Direct `scripts/tractor-reap` execution is acceptable only after verifying its
`python3` shebang resolves the intended project environment.
Review every candidate before requesting a mutating run: Review every candidate before requesting a mutating run:
- default orphan mode is not repository-scoped; - default orphan mode is not repository-scoped;
@ -163,24 +192,31 @@ Review every candidate before requesting a mutating run:
- `--uds` treats `registry@1616.sock` as removable even if a live default UDS - `--uds` treats `registry@1616.sock` as removable even if a live default UDS
registrar uses it. registrar uses it.
Dry-run output prints only the initially matched root PIDs. A mutating run can
recursively expand those roots to additional descendants when `psutil` is
available. Inspect the descendant process tree separately; `-n` is not exact
signal-set parity and does not by itself authorize signaling unseen children.
The canonical skill owns signaling and unlinking authorization. The canonical skill owns signaling and unlinking authorization.
## Test Layout And Change Mapping ## Test Layout And Change Mapping
| Changed area | Run first | | Changed area | Run first |
|---|---| |---|---|
| `tractor/runtime/`, `_root.py` | `tests/test_local.py`, `tests/test_root_runtime.py`, `tests/test_runtime.py`, `tests/test_rpc.py` | | `tractor/runtime/_runtime.py`, `_state.py`, `tractor/_root.py` | `tests/test_local.py`, `tests/test_root_runtime.py`, `tests/test_runtime.py`, `tests/test_rpc.py` |
| `tractor/runtime/_portal.py`, `_rpc.py` | `tests/test_rpc.py`, `tests/test_cancellation.py` |
| `tractor/runtime/_supervise.py` | `tests/test_cancellation.py`, `tests/test_spawning.py` |
| `tractor/discovery/` | `tests/discovery/`, `tests/test_local.py` | | `tractor/discovery/` | `tests/discovery/`, `tests/test_local.py` |
| `tractor/ipc/` | `tests/ipc/`, `tests/test_2way.py`, `tests/test_shm.py` as relevant | | `tractor/ipc/` | `tests/ipc/`, `tests/test_2way.py`, `tests/test_shm.py` as relevant |
| `tractor/spawn/` | `tests/test_spawning.py`, `tests/discovery/test_multi_program.py`, cancellation tests | | `tractor/spawn/` | `tests/test_spawning.py`, `tests/discovery/test_multi_program.py`, `tests/test_cancellation.py` |
| `_context.py`, `_streaming.py` | context, advanced-streaming, and legacy-streaming tests | | `tractor/_context.py`, `_streaming.py` | `tests/test_context_stream_semantics.py`, `tests/test_advanced_streaming.py`, `tests/test_legacy_one_way_streaming.py` |
| `to_asyncio.py` | `tests/test_infected_asyncio.py`, `tests/test_root_infect_asyncio.py` | | `tractor/to_asyncio.py` | `tests/test_infected_asyncio.py`, `tests/test_root_infect_asyncio.py` |
| `tractor/msg/` | `tests/msg/` | | `tractor/msg/` | `tests/msg/` |
| `tractor/devx/` | `tests/devx/`; debugger tests use pexpect and are comparatively slow | | `tractor/devx/` | `tests/devx/`; debugger tests use pexpect and are comparatively slow |
| `_exceptions.py` | remote-exception, registered-error-type, and cancellation tests | | `tractor/_exceptions.py` | `tests/test_remote_exc_relay.py`, `tests/test_reg_err_types.py`, `tests/test_inter_peer_cancellation.py`, `tests/test_cancellation.py`, `tests/msg/` |
Current subdirectories include `discovery/`, `ipc/`, `msg/`, `devx/`, and Current subdirectories include `discovery/`, `ipc/`, `msg/`, `devx/`, and
`trionics/`. `tests/spawn/` currently contains no source tests. `trionics/`. There is no `tests/spawn/` directory.
## Expected Outcomes ## Expected Outcomes

8
.gitignore vendored
View File

@ -121,14 +121,6 @@ snippets/
.claude/skills/resolve-conflicts .claude/skills/resolve-conflicts
.claude/skills/inter-skill-review .claude/skills/inter-skill-review
# /taken-export specifics
.claude/skills/taken-export
.opencode/skills/taken-export
.ai/taken/exports/
# opencode local command deployment
.opencode/commands/
# /open-wkt specifics # /open-wkt specifics
.claude/skills/open-wkt .claude/skills/open-wkt
.claude/wkts/ .claude/wkts/

View File

@ -0,0 +1,42 @@
---
model: openai/gpt-5.6-sol
service: opencode
session: 76c5d31c-5a2f-4503-9b16-410ee7f4fab3
timestamp: 2026-08-22T02:25:26Z
git_ref: 5562fd9a
scope: config
substantive: true
raw_file: 20260822T022526Z_5562fd9a_prompt_io.raw.md
---
## Prompt
Perform a full Tractor repository scan for related `ai.skillz` work,
then correct the run-tests landing branch, prune unrelated `.gitignore`
additions, preserve only the focused migration, and provide canonical
deployment commands.
## Response summary
Audited all local branches, worktrees, affected-path history, deployment
state, canonical skill dependencies, and current Tractor harness behavior.
Corrected the local test reference where it overstated cleanup safety or
omitted current environment, platform, debugger, timeout, and CI details.
Narrowed `.gitignore` to the three managed `run-tests` deployment blocks.
## Files changed
- `.claude/skills/run-tests/test-harness-reference.md` - correct the
project-specific test and cleanup contract.
- `.gitignore` - remove unrelated deployment ignores from this migration.
- `ai/prompt-io/opencode/20260822T022526Z_5562fd9a_prompt_io.md` - record
the migration review provenance.
- `ai/prompt-io/opencode/20260822T022526Z_5562fd9a_prompt_io.raw.md` -
preserve the unedited response record.
## Human edits
The human required an existing-work scan after duplicate implementation
was discovered, approved correcting the landing branch during PR #481
review, and directed removal or reconciliation of unrelated ignore rules.
No direct source-line edits were made by the human.

View File

@ -0,0 +1,24 @@
---
model: openai/gpt-5.6-sol
service: opencode
timestamp: 2026-08-22T02:25:26Z
git_ref: 5562fd9a
diff_cmd: git diff HEAD~1..HEAD
---
Audit Tractor's repository-wide `ai.skillz` state and correct the
`wkt/ai_skillz_run_tests_landing` migration before landing it.
> `git diff HEAD~1..HEAD -- .claude/skills/run-tests/test-harness-reference.md`
The harness reference is corrected against current Tractor behavior:
environment overrides, CI/platform matrices, randomized registry
addresses, interactive debugger capture, timeout mechanisms, stackscope
artifacts, reaper platform limits, dry-run expansion, and exact
change-to-test mappings.
> `git diff HEAD~1..HEAD -- .gitignore`
Unrelated Taken and broad OpenCode command ignore additions are removed;
only the managed canonical `run-tests` link and command blocks remain in
this migration.