Pharos Framework

← Back

Native Spawn/Capture Contract

This contract records the current native spawned-app execution boundary after the staged EPY/C refactor extracted:

  • argv assembly into src/native_runtime/c/native_spawn_argv.c
  • multipart temp-body lifecycle into src/native_runtime/c/native_spawn_temp_body.c
  • shared POSIX execv capture into src/native_runtime/c/native_process_capture.c

The goal is to keep the highest-risk execution behavior explicit while the remaining higher-level orchestration still lives in src/native_runtime/c/pharos_runtime.c.

This boundary is current implementation reality, not the long-term ideal. The preferred direction is to exercise spawned compiled-host behavior through native-first local checks more often so shell/native semantic drift is discovered early.

Primary native surfaces

Current primary files:

  • src/native_runtime/c/pharos_runtime.c
  • src/native_runtime/c/native_spawn_argv.c
  • src/native_runtime/c/native_spawn_temp_body.c
  • src/native_runtime/c/native_process_capture.c

Cases that must remain stable

1. Non-multipart compiled app request success

For non-multipart forwarded app requests, the native runtime must:

  • assemble argv deterministically
  • pass request body through --form
  • capture child stdout/stderr through the shared execv capture path
  • return child output bytes unchanged to the caller when the child exits 0

2. Multipart compiled app request success

For multipart forwarded app requests, the native runtime must:

  • materialize the request body into a temp file
  • pass that path through --body-file
  • avoid inlining multipart bytes into argv
  • clean up the temp file after capture completes

3. Child non-zero exit handling

If the spawned compiled app exits non-zero, the native runtime must:

  • preserve captured output for diagnostics when available
  • surface a 502 Bad Gateway response through higher-level orchestration
  • preserve the failure reason path currently labeled app_host_exit

4. Empty or invalid child response handling

If the child returns no response bytes, the native runtime must treat that as failure at the higher-level request boundary.

Current native behavior is fail-closed:

  • empty response → 502 Bad Gateway
  • request error logging remains enabled for the failure path

5. Shared capture primitive consistency

The shared POSIX capture primitive serves both:

  • shell/runtime bridge command capture
  • compiled app request execution capture

That shared primitive must continue to preserve:

  • stdout/stderr merged capture
  • exit-code-based success/failure translation
  • no shell interpolation for compiled app request execution

Platform note

This contract does not newly claim parity across every target platform.

Current state remains:

  • POSIX native capture path is implemented and active
  • Windows and WASM/non-POSIX capture paths remain stubbed/blocked where unchanged

Any future expansion of non-POSIX process capture must be documented explicitly rather than assumed.

Preferred convergence check path

Where supported locally, prefer:

scripts/check.sh native-compiled-flow

That flow builds and smokes the native target before server-smoke verification, making spawned compiled-host execution part of the routine local validation path instead of a release-only edge surface.