[pitboss/grind] deferred session-0001 (20260520T233019Z-6958)

This commit is contained in:
pitboss 2026-05-20 19:26:01 -05:00
parent f9bd51c024
commit 3b49b4d4b5
5 changed files with 88 additions and 7 deletions

View file

@ -723,6 +723,8 @@ fn emit_middleware_harness(handler: &str, name: &str) -> HarnessSource {
r#"{preamble}
puts "__NYX_MIDDLEWARE__: " + {name:?}
require 'stringio'
# Rack-shape middleware: class with #call(env).
env = {{
'REQUEST_METHOD' => 'POST',
@ -731,7 +733,6 @@ env = {{
'rack.input' => StringIO.new($nyx_payload),
'nyx.payload' => $nyx_payload,
}}
require 'stringio'
if Object.const_defined?({handler:?})
cls = Object.const_get({handler:?})
@ -1233,7 +1234,8 @@ fn invoke_for_shape(spec: &HarnessSpec, shape: RubyShape, entry_fn: &str) -> Str
RubyShape::RackMiddleware => {
let cls = entry_class_from_spec(spec);
format!(
r#" cls = Object.const_defined?({cls:?}) ? Object.const_get({cls:?}) : nil
r#" require 'stringio'
cls = Object.const_defined?({cls:?}) ? Object.const_get({cls:?}) : nil
if cls
inner = cls.respond_to?(:new) ? (cls.method(:new).arity == 0 ? cls.new : cls.new(nil)) : nil
env = {{
@ -1243,7 +1245,6 @@ fn invoke_for_shape(spec: &HarnessSpec, shape: RubyShape, entry_fn: &str) -> Str
'rack.input' => StringIO.new(($nyx_request[:body] rescue '')),
'nyx.payload' => $nyx_payload,
}}
require 'stringio'
status, headers, body = inner.call(env)
Array(body).each {{ |chunk| print(chunk.to_s) }}
end"#,

View file

@ -775,7 +775,20 @@ pub fn run(
}
}
SandboxBackend::Auto => {
if docker_available() && harness_is_interpreted(&harness.command) {
// Docker containers run the interpreter image's bare runtime
// (python:3-slim, node:20-slim, ruby:3-slim, ...) with no
// network access under NetworkPolicy::None. Harness shapes
// that depend on packages declared via requirements.txt /
// package.json / Gemfile / composer.json can be served from
// the host build cache by prepare_*, but the container has
// no way to fetch them at exec time. Route to the process
// backend in that case so the harness picks up the host
// venv / node_modules / vendor dir already prepared.
let needs_host_deps = harness_needs_host_deps(harness);
if docker_available()
&& harness_is_interpreted(&harness.command)
&& !needs_host_deps
{
run_docker(harness, payload_bytes, opts)
} else if docker_available() && harness_is_native_binary(&harness.command) {
run_native_binary_docker(harness, payload_bytes, opts)
@ -788,6 +801,33 @@ pub fn run(
}
}
/// True when the harness workdir carries a dependency manifest that the
/// docker backend has no mechanism to materialise inside the container.
///
/// `prepare_python` / `prepare_node` / `prepare_php` / etc. resolve these
/// against the host build cache before the run, so the process backend
/// already has a fully-populated venv / node_modules / vendor dir to
/// invoke. The docker backend, on the other hand, mounts the workdir
/// into a bare interpreter image (python:3-slim, node:20-slim, ...) and
/// runs under `--network=none`, leaving no path for an in-container
/// `pip install` / `npm install` / `composer install` to fetch the deps.
/// Routing those shapes to the process backend keeps the verifier honest
/// on dev hosts where docker is available but the bare image lacks the
/// third-party libs the entry source imports.
fn harness_needs_host_deps(harness: &BuiltHarness) -> bool {
const MANIFESTS: &[&str] = &[
"requirements.txt",
"Pipfile.lock",
"pyproject.toml",
"package.json",
"Gemfile",
"composer.json",
];
MANIFESTS
.iter()
.any(|name| harness.workdir.join(name).exists())
}
/// Phase 20 (Track E.4): dispatch the Firecracker backend.
///
/// When `--features firecracker` is off, the call returns