Nocter v0.31.0
Nocter v0.31.0 Release Notes
Nocter v0.31.0 adds complete standard-output and standard-error capture to the synchronous
subprocess API. A consumed Command now returns an owning Output containing arbitrary bytes from
both streams and the child's typed terminal status. The only implemented host and native target
remains arm64-darwin.
Captured Commands
std/process now exposes:
use std/process.Command
use std/string.String
var command = Command.new("./helper")?
command.arg("one argument")?
let output = command.output()?
let stdout = String.from_utf8(&output.stdout)?
let stderr = String.from_utf8(&output.stderr)?
Command.output inherits standard input, the environment, and the working directory. It creates
exactly one child, captures stdout and stderr simultaneously, waits for that exact child, and
returns only after both byte streams reach end of file and the terminal state is observed. The
returned Output owns all three values and contains no live descriptor or process handle.
The streams are Vec<u8> rather than String because process output need not be UTF-8. A caller
that knows a text contract validates it explicitly with String.from_utf8. Each stream preserves
its own byte order; no ordering between stdout and stderr is invented.
Closed Capture Lifecycle
Both finite pipes are drained through one fair readiness loop while the child can still run. This
prevents a child that fills either stream from deadlocking behind a sequential whole-stream read.
Hangup does not discard buffered bytes, interrupted operations are retried, and descriptors are
normalized away from standard descriptors before child setup.
A private close-on-exec report distinguishes standard-descriptor setup failure from executable
rejection without reserving a child exit code. Every representable post-fork error path closes
owned descriptors and attempts to observe the exact child before returning. Nonzero exit and signal
termination remain successful observations and retain all bytes written before termination.
Practical Integration
The new subprocess-output package example invokes a repository-owned helper, passes one
whitespace-bearing argument, verifies a typed nonzero exit, converts both streams explicitly to
UTF-8, and prints a deterministic report. The same authored source crosses native execution,
formatter checks, semantic diagnostics, hover, completion, declaration and implementation
navigation, and installed-home qualification.
Compatibility and Non-goals
This release adds API without changing Command.status or existing process argument, environment,
current-directory, exit, and abort behavior. It does not add an asynchronous child handle,
incremental stream access, input redirection, caller-provided descriptors, merged output, bounded
capture, timeout, PATH search, shell execution, environment edits, working-directory overrides,
or another native target.
Candidate Qualification
Release-content commit c06cb1b1ca86622c926b4a4dcbfd08fb481acb96 passed two independent
locked workspace runs with 1,539 tests passed, zero failed, and one ignored in each run. The
ignored public-HTTPS acquisition test passed separately. Warnings-denied all-target Clippy,
no-default-features checking, deterministic documentation, formatter checks, and repository
validation also passed.
Two independent optimized builds produced the same archive and installed home. The retained local
archive is 8,286,135 bytes and has SHA-256
914ad97e360f8451aa2c212a21445af7ec457d1cc64d102f64a181fd6c563453. Its isolated installed home
passed version and integrity checks, every public example, package run/build/test/graph operations,
the exact text-banner, stdin-prefix, subprocess-status, and subprocess-output process
contracts, framed LSP requests, immutability checking, and compiler and standard-library tamper
rejection. Publication reuses that retained candidate without rebuilding it.