107 lines
3.9 KiB
Markdown
107 lines
3.9 KiB
Markdown
|
|
---
|
||
|
|
model: claude-opus-4-7[1m]
|
||
|
|
service: claude
|
||
|
|
timestamp: 2026-06-01T23:14:29Z
|
||
|
|
git_ref: 0e3e008b
|
||
|
|
diff_cmd: git diff HEAD~1..HEAD
|
||
|
|
---
|
||
|
|
|
||
|
|
# RETROACTIVE — original model output not preserved
|
||
|
|
|
||
|
|
This `.raw.md` would normally contain the verbatim
|
||
|
|
pre-human-edit response from the design session that
|
||
|
|
produced the staged `_subproc.py` module + tests. That
|
||
|
|
session's transcript is not available, so this file
|
||
|
|
serves as a diff-pointer placeholder + transparency
|
||
|
|
note.
|
||
|
|
|
||
|
|
## Authoritative artifact
|
||
|
|
|
||
|
|
The committed code IS the artifact of record. Once the
|
||
|
|
companion commit lands, the unified diff is:
|
||
|
|
|
||
|
|
> `git diff HEAD~1..HEAD -- tractor/trionics/_subproc.py`
|
||
|
|
> `git diff HEAD~1..HEAD -- tests/trionics/test_subproc.py`
|
||
|
|
> `git diff HEAD~1..HEAD -- tractor/trionics/__init__.py`
|
||
|
|
|
||
|
|
Before committing, substitute `--cached` for the
|
||
|
|
pre-commit form.
|
||
|
|
|
||
|
|
## What is NOT here
|
||
|
|
|
||
|
|
Because this is retroactive:
|
||
|
|
- No verbatim chain-of-thought / discussion prose from
|
||
|
|
the design session.
|
||
|
|
- No rejected alternatives the model considered before
|
||
|
|
arriving at the final shape (e.g. whether the
|
||
|
|
rc-check should live inside `own_tn` vs after it; the
|
||
|
|
`_UNSET` sentinel vs a `None`-means-DEVNULL
|
||
|
|
convention; `io` vs `info` as the default relay
|
||
|
|
level).
|
||
|
|
- No pre-edit code blocks as the model first emitted
|
||
|
|
them, separable from any user cleanup applied before
|
||
|
|
the diff was staged.
|
||
|
|
|
||
|
|
## Inferred design choices visible in the final code
|
||
|
|
|
||
|
|
(Documented here because they're the kind of decision
|
||
|
|
detail an unedited raw transcript would have captured.)
|
||
|
|
|
||
|
|
1. **Post-drain rc-check in the supervisor coro body,
|
||
|
|
AFTER `own_tn.__aexit__`.** Placing the
|
||
|
|
`CalledProcessError` raise here (not inside
|
||
|
|
`own_tn`) means the EG-unwrap happens at the OUTER
|
||
|
|
`tn.start()` boundary — callers do `collapse_eg()`
|
||
|
|
if they want bare. Doing the raise INSIDE `own_tn`
|
||
|
|
would cancel the still-draining relay reader
|
||
|
|
mid-flight and lose stderr lines.
|
||
|
|
|
||
|
|
2. **`_UNSET` sentinel for `stdout`.** A plain default
|
||
|
|
of `None` couldn't distinguish "use the safe
|
||
|
|
`DEVNULL` default" from "caller explicitly passed
|
||
|
|
`None` (inherit, presumably knowingly)". The
|
||
|
|
sentinel keeps the SAFE default while letting power
|
||
|
|
users opt into inherit.
|
||
|
|
|
||
|
|
3. **`relay_level='io'` (custom level 21).** Chosen to
|
||
|
|
sort just above stdlib `INFO`=20 so a default
|
||
|
|
`--ll info` shows the relay, but it remains a
|
||
|
|
distinct level so users can filter
|
||
|
|
`tractor.trionics:io` separately. Picking
|
||
|
|
`runtime`=15 would have made the relay invisible at
|
||
|
|
default verbosity (a footgun for daemon supervisors
|
||
|
|
whose whole point is "I want to see this output").
|
||
|
|
|
||
|
|
4. **Reader is MANDATORY, not opt-in cosmetic.** With
|
||
|
|
`stdout=PIPE` / `stderr=PIPE` we OWN the drain
|
||
|
|
responsibility — there's no `trio.capture_*` running
|
||
|
|
under the hood here. The ~64KiB OS pipe buffer
|
||
|
|
means a child writing more than that without us
|
||
|
|
reading hangs at `write()` — a deadlock that won't
|
||
|
|
show up in small-output tests, which is why the
|
||
|
|
200KiB-no-newline test is in the suite.
|
||
|
|
|
||
|
|
5. **`task_status.started(trio_proc)` BEFORE the
|
||
|
|
`own_tn` exits.** Without this, `tn.start()` would
|
||
|
|
block until the child exits — losing the "start a
|
||
|
|
long-lived daemon and continue with parent work"
|
||
|
|
use case. With it, the parent gets the live process
|
||
|
|
handle immediately and the supervise+relay tasks
|
||
|
|
run in the supervisor coro until the child exits.
|
||
|
|
|
||
|
|
6. **`__notes__` via `add_note()` for the CPE
|
||
|
|
`.stderr`.** The `.stderr` attribute is what
|
||
|
|
`subprocess` callers expect; the `add_note()` is
|
||
|
|
what trio's exception-rendering shows. Both wired so
|
||
|
|
programmatic AND human consumers see the stderr at
|
||
|
|
teardown.
|
||
|
|
|
||
|
|
## Honesty statement
|
||
|
|
|
||
|
|
This file's content is RECONSTRUCTED from the staged
|
||
|
|
code, not extracted from a verbatim model transcript.
|
||
|
|
The prompt-io skill's intent is for the `.raw.md` to
|
||
|
|
be a pre-edit fossil; that's not possible here. Future
|
||
|
|
work should write the prompt-io entry DURING the
|
||
|
|
design session.
|