Retain the accepted authority boundaries, task-admitted settings and independent critic/author evidence. Recover the held fixes and preserve the ordinary skill gate ABI with optional author facts.
Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
- module-handle declared sets updated to the folded reality (hold controls,
body parser, quiz drain, cached ledger read)
- node-resolver tests retarget the campaign guard/attestation seams; frozen
ToolEntry replaced via dataclasses.replace
- sweep-refresh test targets ouroboros.server_maintenance (campaign owner)
- process-signal tests drive the typed dispatcher; the upstream regex-fallback
pin replaced by the D02 contract pin (prose forges no process facts) and the
stale regex-fallback comments corrected
- routing-decision/find-child fixtures stamp _schema_version (ABI 7.0 readers
quarantine unstamped rows); emit-and-wait patch retargets control_routing
- terminal-writers manifest gains _rewrite_execution_evidence (cursor/backfill)
- core catalog pins updated for send_links/escalate (owners: core_artifacts);
node argv policy moved beside its PATH-prepend half in extension_child_catalog
to keep extension_plugin_api at the 1000-line bound
- classification golden regenerated per the corpus recipe at 0f715831; three
A.23 approved deltas record the F6-sync classification changes
On macOS the generic process surfaces (run_command, run_script,
start_service, verify_and_record) resolved bare node/npm through the
host PATH, which can point at a Homebrew node the kernel SIGKILLs on
launch (CODESIGNING, ~9ms) while a working signed bundled node ships
inside the application. shutil.which proves existence, not runnability.
process_interpreters.py (renamed from python_interpreter.py; one generic
InterpreterResolutionTrace with a family field, python event payloads
byte-identical) gains the node branch of the resolver: POST-GATES - the
health probe EXECUTES a candidate, so it must sit below the light fence,
shell guards and safety refusals
(test_light_fence_refuses_before_the_node_probe_can_execute pins that a
planted PATH shim's payload cannot run off a refused call); guards
inspect the original argv and the substitution reaches the handler
through a scoped attestation. Ladder: bootstrap_process_path first;
non-local executor backends are skipped; a healthy PATH node is a
byte-identical no-op in argv, child env, rendered prose and receipts
(the typed resolution trace event is deliberate observability, symmetric
with python's); a missing or probe-dead PATH node falls back to the
bundled runtime (argv rewrite only for bare node/nodejs; an attested
child-env PATH prepend for npm-family launches and for sh/bash/zsh/dash
bodies found via shell_parse.shell_tokens, wrappers matched by
basename); no usable node runs as written with the probe facts
disclosed - never a pre-block.
ouroboros/node_runtime.py owns the execution-probed health memo
((path, mtime, size)-keyed; missing never cached so a mid-session
install is noticed; a timeout verdict is cached with its probe budget
and re-probed only by a larger one; a relative which() result is never
trusted) and the skill-family policy select_skill_node_runtime
(bundled-first with health rollback), used by skill_exec, companions,
isolated deps, workspace preflight and the world profiler;
platform_layer lazily re-exports the public names (PEP 562, both import
orders pinned).
Handlers publish typed process facts (exit_code, POSIX signal name,
duration_ms, resolved_runtime) through the thread-local seam in
tools/process_facts.py; loop_tool_execution consumes them for the same
call, and the regex harvest over rendered text remains the read
fallback. Verify receipts disclose duration/signal/runtime while the
ORIGINAL check text stays the receipt identity. A signal death (rc < 0)
leaves the cosmetic bucket (POSIX; Windows is a disclosed residual), the
web log renders it as an error, and an executed serial pin proves our
own cancel custody never surfaces as tool_failure. Durations are
monotonic; the filesystem freshness audit keeps its own epoch stamp.
Three adversarial rounds, a triad+scope review round (12 runs) and a
delta + full-scope verification round (4 runs) are dispositioned in the
sprint plan; the accepted findings are folded in (Windows-only token
normalization, padded-head declassification, relative-which no-op on
both resolver lanes, basename-matched shell wrappers, case-aware env
overlay merge shared with the companion manifest lane, budget-scoped
timeout memo, size-gate surgery).