hack.foo
Native backend (beta)

Command contract

An explicit HACK_RUNTIME_BACKEND=native selection delegates an authored .hack/hack.project.json project to the separate native foreground owner. The current command slice supports whole-project foreground up and restart, owner-mediated down and explicit stored-generation down --recover, saved-run ps, finite service logs --no-follow, noninteractive service exec and one-off service run on macOS with an absolute HACK_NATIVE_BINARY and private canonical HACK_NATIVE_HOME. It requires the caller's separately prepared native provider pool and matching runtime binary. It does not install or select a runtime automatically. An omitted backend continues to use the Compose command owner.

This bounded native consumer requires each service's image to be an immutable sha256: image content ID, such as the image_id returned by a successful runtime ensure-image acquisition. Keep that acquisition's pinned-reference and archive evidence. A registry tag or repository@sha256:manifest-digest is not the content ID. The native planner (graph native plan and frontend-plan) refuses it with the same closed native_graph_admission code that execution uses, so up fails at its native-plan stage before it reserves a startup intent. config validate reports the same refusal when HACK_RUNTIME_BACKEND=native is set; without it, validation stays backend-neutral because Compose runs tags and digests. Do not substitute a mutable image or bypass the image identity guard.

HACK_RUNTIME_BACKEND=native \
HACK_NATIVE_BINARY=/absolute/candidate/hack-native \
HACK_NATIVE_HOME=/absolute/private/candidate-home \
./dist/hack --path /absolute/project up

The native planner admits image workloads, exec readiness, initializer jobs and dependencies with the ordinary project network and outbound mode. It also admits one read-only project source mount per selected workload, using the existing host-mounted source mode and root .. The provider pool must already contain the exact explicitly approved unfiltered live project share. That existing virtiofs share grants the guest writable access to the whole tree; only the individual workload bind is read-only. This command does not enroll the share or change pool mounts. Host edits remain visible. A selected directory allows descendant edits; a selected regular file allows in-place edits but refuses replacement of its inode. Selected path/ancestor aliases, identity or permission changes refuse, while exact owned shutdown remains possible after the host source is moved or deleted and preserves host data.

Writable source mounts, source acquisition, file inputs and routing remain outside this bounded frontend. The existing closed two-owned-bridge graph capability keeps its separate receipt and refuses source/storage intersections. Finite typed host lifecycle hooks use the supervised frontend owner described below. Unsupported intent must refuse before managed value resolution and provider work. Early typed input capability refusals retain E_NATIVE_PROJECT_UNSUPPORTED without exposing compiler diagnostics or creating native source/start/run authority. --detach, --json for up and restart, service subsets and unsupported lifecycle operations except owner-mediated down refuse before input acquisition. --branch supplies an explicit native namespace; its omission uses the canonical project namespace without inferring a Git branch. Profile and env selection keep their compiler contracts. --env base bypasses inherited overlays with an explicit base selection; omitting --env retains the authored/local default.

The separate persistent-storage capability requires the runtime's pinned sibling witness tool and retains its own ownership and recovery checks. It cannot be combined with the supervised host-process capability below.

Support matrix

Every slice requires macOS; any other host refuses before input acquisition. Each row lists the admitted form and the requests that refuse with E_NATIVE_PROJECT_UNSUPPORTED before managed value resolution, compiler work or provider contact. A refusal names no option value, path or project detail.

CommandSupported formRefuses before input acquisition
upWhole-project foreground; --branch, --profile and --env (including --env base) keep their compiler contracts--detach, --json, --recover, service subsets, single-service, command, workdir, follow, tail and format options, other unsupported options
downWhole-project owner-mediated stop of a ready generation through its live foreground owner or private no-host endpoint--json, --detach, --profile and --env overrides, service subsets including an empty selection, single-service, command, workdir, follow, tail and format options
down --recoverExplicit retirement of a complete stored generation whose owners are dead, or of a pending startup intent that never reserved runtime state; omit --profile--json, --detach, explicit empty or named --profile, --env overrides, service subsets, single-service, command, workdir, follow, tail and format options
psps and ps --json for the exact saved project and explicit --branch--profile, --env, service subsets or a single service, --recover, --detach, command, workdir, follow, tail and format options
logslogs SERVICE --no-follow with --tail from 1 through 1000 (default 200), plain or --jsonFollow mode (the default), omitted, multiple or malformed service selection, non-integer or out-of-range --tail, pretty format, time and query filters, --profile, --env, --recover, --detach, command and workdir options
execexec SERVICE -- COMMAND ARG... with closed stdin, no TTY and an optional absolute --workdirEmpty command or empty first argument, NUL bytes, more than 256 arguments, an argument over 16 KiB or 64 KiB in total, relative --workdir, interactive or TTY input, --json, --profile, --env, service subsets, follow, tail and format options, --recover, --detach
runrun SERVICE -- COMMAND ARG... through a ready foreground owner, closed stdin, no TTY, optional absolute --workdir; member must have no mountsThe exec option refusals above; source, persistent-data or private-env mounts refuse before the one-off effect
restartWhole-project proven stop followed by fresh foreground up; --branch, --profile and --env select the fresh generationService subsets, --json, --detach, --target, recovery and other unsupported foreground options; missing or unproven stop prevents startup

Both backends remain experimental. This table records the refusal boundary of the current slices; it is not a parity claim against the Compose owner and does not report installed live acceptance.

Foreground up

Startup shares the configured HACK_COMPOSE_STARTUP_TIMEOUT_MS budget across input preparation and native review, with a native maximum of 300000 milliseconds. Each startup compiler call is bounded by the time the startup budget has left, capped at 60 seconds, rather than by a fixed 10-second clock. Compiler calls outside startup (the down hooks' input check after Ctrl-C or a stop request, and checks after ready) have no startup budget and take the 60-second cap, so a slow host does not fail a graceful stop (HACK-1458). A start that fails or is cancelled after host processes began and before its startup intent exists stops those processes, or ends the launch it had begun through its own session token, before it returns. A teardown it cannot prove keeps the host process records retained. If the graph fails before Ready after reserving the startup intent, host teardown additionally requires the original producer and readers to settle and the original graph group to be absent. Startup reacquires unchanged host inputs under the hard-stop signal, then authenticates an exact Removed receipt and absent resource observations before stopping the owned host session. A live, foreign, unknown or unreserved receipt, changed input, or hard cancellation keeps this attempt retained. Startup refusals identify a fixed owning stage and, when available, a closed compiler or native error code. They omit arbitrary errors, child output, paths and values. If startup fails before publishing a receipt and the later retirement inspection also refuses, the captured native startup code takes precedence over the inspection code. That preserves the failure's owning boundary; it does not prove cleanup. Retained bindings and recovery requirements stay in force. These diagnostics do not grant retry or cleanup authority.

A native consumer can refuse after the startup intent is reserved but before it reserves any runtime journal, for example when its review changes, the engine cannot be reached or startup is canceled. (A repository@sha256: image used to reach execution this way; the planner now refuses it first.) Such a run has no receipt, so the Removed retirement inspection can never succeed. After the consumer process has settled, startup asks the native runtime to inspect the exact run. Startup retires the startup intent and its source envelope only when the runtime refuses native_graph_unreserved: the run's journal directory is exactly absent under private state directories, and no foreground owner is published for the run. The failure then reports outcome unreserved with the original native code, and ps reports not_started. Any other inspection result keeps the attempt retained. Examples include native_graph_receipt for damaged or foreign evidence, native_graph_foreground for a published owner, and a stopped runtime. This applies only to attempts without lifecycle hooks, host processes or a live-stop owner. A canceled startup that retains nothing (not-started, such as Ctrl-C during preflight, unreserved, or confirmed removal) prints a cancellation note and exits 130; a canceled start that retained evidence still fails. Readiness requires authenticated current observations and unchanged input before publication. The foreground owner remains attached until owned shutdown finishes; Ctrl-C requests that shutdown. Exact durable Removed evidence retires the tagged native run and startup intent. Unknown, changed or live cleanup retains the attempt and refuses replay; a missing ready mapping does not authorize a fresh start.

On macOS, up --detach and restart --detach refuse with E_USAGE and the same one-line message as an image project: native up runs in the foreground only, so run it without --detach in its own terminal, use ps and logs from another terminal, and press Ctrl-C to stop it.

After native review and before it reserves the startup intent, up asks the runtime for its read-only status. A stopped runtime (any phase other than running, or a dead runtime process) refuses at stage reservation with native code runtime_not_running. The CLI reports E_DOCKER_UNAVAILABLE: "Native runtime is not running; nothing was started." No intent is retained, so ps keeps reporting not_started. An inconclusive status reply does not refuse. The check is advisory: if the runtime stops after it, the start fails later and, when its intent was already reserved, keeps that evidence; the CLI then still reports E_DOCKER_UNAVAILABLE, and ps reports pending until the retained attempt is inspected.

Saved-run ps

ps and ps --json issue one authenticated current status request for the exact saved project and explicit branch selection. Text output lists service, container, current state and current health. JSON uses the ordinary result envelope with data.backend: "native", data.status, data.run, historical data.phase, and data.items; each item includes service, container, state, health and exitCode. Only fresh runtime observations supply state and health. Stored readiness and phase do not prove that a service is still live.

A project with no saved attempt reports not_started; a retained startup intent without a Ready mapping reports pending with no confirmed service rows. pending covers a start that is still in progress and a failed start whose reserved intent was retained as evidence; Hack does not guess which, because only the owner's cleanup proof may retire that intent. When no startup is running, down --recover can retire the attempt if it never reserved runtime state (see below). When a Ready generation is saved but the candidate runtime is stopped (native code runtime_not_running, or the authenticated native_graph_foreground control code with that exact cause), ps exits 0 and reports runtime_not_running with the saved data.run, a null data.phase and no items; text output prints "Native runtime is not running; no services are running." A dead owner, uncertain recovery, changed selection, or malformed or mismatched reply refuses with unconfirmed status. The reader holds and rechecks project, private directories, saved record identities and the selected executable across its single bounded request. It does not compile or read authored values, resolve env, run hooks, start workloads, repair state or perform cleanup. Cancellation waits for the owned request to settle. Profiles, env overrides, service subsets and other ps options are unsupported. Finite one-off run and whole-project restart are described below.

Owner-mediated down and down --recover

Ordinary whole-project down asks the live foreground owner of a ready generation to stop. A finite-hook generation uses the private per-run capability described under host lifecycle hooks below. down also supports a ready no-host generation, including persistent-storage plans. Its private no-host endpoint is issued by the original held startup admission before public Ready. It asks that same foreground owner to stop; no host declaration, hook permit, new controller or stored-PID signal is created. Success requires authenticated Removed, the original child and detached group's settlement, and exact endpoint/start/Ready/source retirement. Compute shutdown retains persistent data; this command adds no volume deletion authority. A missing, changed or dead endpoint refuses. Partial publication or retirement keeps startup evidence blocked. Legacy no-host version 1 records remain ineligible for dead-owner recovery. New version 2 records capture the original native child while its foreground owns it: PID, birth, executable identities, UID, host boot session, process group and session. Recovery uses two bounded complete process-metadata observations. It refuses any occupied original PID, including reuse or a zombie, and every live member of its former group or session. Unknown live membership refuses. Explicit zombie rows whose identity and state match both observations remain in the result, with unavailable session membership counted separately. This proves no live members at the observations; it does not prove the numeric group/session is absent. It never signals a saved numeric group. The original owner separately publishes one bound settlement observation only after its captured exit, drain and existing group-absence check. That observation cannot replace fresh recovery checks. A live SID lookup race permits an entirely fresh attempt only if a complete bounded reread positively observes that PID missing. Both earlier observations and their SID mappings are discarded; two new complete observations must fit the original monotonic budget, including any further proven disappearance. Disappeared PIDs remain only as denial facts: any reappearance in a later census or diagnostic reread refuses. State changes, still-live or unavailable rows, failed rereads and exhausted budget refuse. No individual row is skipped and no deadline is renewed.

Darwin's ps state implementation maps SZOMB to Z. The XNU exit path waits active asynchronous I/O and invalidates open files before publishing that state. Zombie process-group metadata can persist until reap, so unavailable SID on a stable Z row is distinct from unknown live membership. Changed, disappeared or newly observed zombie identities refuse rather than borrowing stale state.

The existing recovery owner retains its leases and exact Ready/start/source, native owner and receipt bindings before and after cleanup. It phase-retires only the admitted endpoint and optional settlement record after authenticated Removed and null observations. Replaced, malformed, live or unknown evidence stays retained. Graph4 recovery additionally requires all data enrolled and the exact installed tool root/helper assertion, matching the native owner; source and topology families remain separately refused. These source controls do not qualify installed kill/recover/up or retained SQL behavior. Portable private-filesystem and stand-in lifecycle controls cover this boundary; installed Source4 SQL retention through public down/up remains a separate runtime gate.

down --recover explicitly retires a complete stored native generation whose foreground publisher and frontend admission owner are both dead on the same host boot. New version 4 native publications use the kernel boot-session UUID, which remains independent of calendar clock correction. Recovery requires the exact stored Ready, startup intent and private source envelope, and the original guest incarnation. Live owners, older version 2 dead publications, partial startup, pending writes, changed files and rebooted guests refuse. Env/profile changes, service subsets and --json are unsupported for this operation. It neither recompiles authored input nor acquires managed values or starts a provider. Omit --profile to recover the stored generation; explicit empty or named profile overrides both refuse.

Repeating down --recover after confirmed retirement is a read-only no-op, including when authenticated completed recovery history remains. It does not contact the native runtime or acquire recovery locks. Incomplete recovery, pending writes, retained owner records and changed history still select recovery or refuse; they do not qualify for the no-op.

When the selection has a retained startup intent but no Ready mapping and no recovery intent, down --recover takes a different path. It handles only an incomplete startup that never reserved runtime state. One example is an attempt retained by an earlier CLI before this retirement existed. The command first takes a fresh startup admission. A live or interrupted foreground CLI still holds that admission, so the command refuses as busy in that case. It also requires that no Ready mapping, lifecycle-hook owner or live-stop owner exists. It then inspects the exact run. It retires the start intent and the validated source envelope only when the native runtime refuses native_graph_unreserved. It removes the source first, so an interrupted retirement keeps the start intent blocking. Any receipt, any other refusal, or a successful inspection retains every file. This path does not compile input, acquire values, serve a run or touch guest resources.

The closed version 3 publication and version 1 recovery selector remain supported with their original calendar boot qualifier; clock drift conservatively refuses that legacy recovery. New version 4 owners use version 2 UUID selectors. Missing, malformed or unavailable UUIDs refuse; no old record is migrated or given inferred session authority. PID birth/executable, peer, inode, gate and run-lock checks remain.

Recovery commits a distinct private intent before calling the Rust cleanup owner. The original raw selectors and resource inventory remain fixed through retries; current cleanup phases may advance. Before retiring each frontend file, the owner inspects the exact native receipt and requires all resources Removed with null observations. A committed retirement phase alone permits the corresponding file's expected absence. Pending writes and replacements remain retained refusals. The recovery lease blocks ordinary startup throughout this work. Completed frontend history is archived under fresh startup admission before a later generation can start; incomplete history never permits automatic takeover. Persistent data stays retained, and no recovery operation reboots the guest or allocates new resources.

Dead recovery lease takeover retains its private directory and commits the exact next owner file before replacing the old owner. A recorded candidate may be pending or already published after interruption; both forms must match the saved inode and bytes before a fresh lease is issued. Separate committed release flags authorize only the corresponding owner/directory absence. An unrecorded pending candidate and an interrupted completed-history hardlink archive remain retained refusals; this operation does not repair arbitrary partial lock or file publications.

The native receipt and source paths are distinct from strict Compose v1 artifacts. Image-only graph receipts remain v2; source-bearing graph receipts use a closed v3 binding, distinct from the existing foreground publication-owner v3. Ready/control envelopes remain v2. Dead-owner recovery of source-bearing receipts is not admitted by the separately qualified image-only recovery path. No native hash substitutes for a normalized Compose hash. Source and fake-driver checks do not qualify an installed frontend, a live provider, the full authored corpus, actual dead-owner recovery or resource overhead; those remain separate gates.

Whole-project restart

restart with HACK_RUNTIME_BACKEND=native stops the current authored generation and then starts a fresh foreground generation in one command. The stop half is the same owner-mediated whole-project down: it asks the live foreground owner, or the private no-host endpoint of a ready no-host generation, to stop and requires authenticated Removed with exact endpoint/start/Ready/source retirement. Nothing starts until that proof completes. A missing, changed or dead owner, an uncertain stop or a cancellation during the stop refuses with E_LIFECYCLE_FAILED, restarts nothing and retains the selected state; a project with no running generation refuses here, so use up. Compute shutdown retains persistent data, and the fresh generation reuses the same project and --branch namespace, so persistent-data identity is unchanged across the cycle. This command adds no volume deletion, data migration or dead-owner recovery authority.

The start half is the ordinary foreground up. It reacquires input and managed values, performs a fresh native review and remains attached until owned shutdown. --profile and --env (including --env base) select the fresh generation exactly as on up; the stopped generation's selection is not reused. Because the start half is up, host.up.before, host.up.after and host.processes run again exactly as on up, after the stopped generation's host.down.before, host.down.after and process stop completed. Startup refusals keep the up contract: a fixed owning stage, a closed compiler or native code and E_STARTUP_INCOMPLETE, E_NATIVE_PROJECT_UNSUPPORTED or, for a stopped runtime, E_DOCKER_UNAVAILABLE. Retained startup evidence from an incomplete retirement refuses the fresh start without replay. A Ctrl-C that arrives after the proven stop and before the fresh start returns 130 with nothing restarted. Each half uses the configured HACK_COMPOSE_STARTUP_TIMEOUT_MS budget separately; neither renews the other.

Service subsets, --json, detached restart, --target and the frontend recovery options refuse with E_NATIVE_PROJECT_UNSUPPORTED before input acquisition or any stop request. Portable stand-in controls cover the stop-then-start ordering, failed-stop retention and cancellation between the halves; installed live restart acceptance remains a separate host-serialized gate.

Finite service logs

An already running authored foreground owner supports logs SERVICE --no-follow on macOS. --tail defaults to 200 and accepts integers from 1 through 1000; --json returns separate stdout/stderr strings and a truncation flag. Plain output preserves those two streams. Follow mode, pretty formatting, time/query filters, profiles, environment overrides and multiple service selections refuse before any input or runtime operation. This is a finite log-read capability, not full logs parity.

The read uses the existing authenticated native control socket and exact admitted service/container, guest boot and run receipt. It refuses a dead/wrong owner, changed authored project/local/source-envelope files, changed frontend mapping, resource replacement or a container restart during the read. The live owner keeps value-free input identity/hash pins; it does not reacquire managed values. Source mounts and persistent-data bindings retain their existing current ownership checks.

Log tails use the Engine's existing limits: at most 1000 lines, a 4 MiB response transport bound, and 16 KiB of JSON-encoded text per output stream with explicit truncation. One 15-second observation budget covers the Engine, source and storage guest checks, within the existing bounded control reply. Cancellation or incomplete child/output settlement withholds the result; it never stops the foreground owner or retries a query. Logs may contain application values and are returned only to the requesting caller; they are never journaled or included in refusal diagnostics. A stopped candidate runtime refuses with E_DOCKER_UNAVAILABLE ("Native runtime is not running; no service logs are available.") and exit 1. Offline controls do not qualify a live provider or application log behavior.

Finite service exec

exec SERVICE -- COMMAND ARG... sends one command to an already running authored service through its authenticated foreground owner. Arguments are literal, including empty arguments, spaces and shell characters. --workdir selects an absolute guest directory; the service's existing environment and user remain in force. Stdin is closed and no TTY is allocated. Interactive input, TTY control, env/profile overrides, multiple services and JSON formatting are unsupported. No shell is inserted.

The owner verifies the admitted service, full resource ownership, guest boot, image, container start generation and current source/data bindings before each exec transport and after completion. The current input and hook permit remain pinned. A changed owner, member, source or container restart withholds the result. This does not start, restart or recover a project and does not acquire managed values.

One 30-second observation budget includes identity proofs and the Engine's existing single exec create, attached start and completion inspection. Known completion preserves the command's exit code and binary stdout/stderr, with up to 1 MiB per stream and an explicit truncation notice. Cancellation or timeout settles the local request but cannot prove guest command termination. Unknown guest completion admits no command output and warns that effects may have occurred. Once a validated completion is being written, cancellation returns 130 and prevents remaining writes; already-written bytes cannot be retracted. No request is replayed and the foreground project is not stopped. Inspect the service before deciding whether another command is appropriate. Offline controls do not qualify installed native exec or live application behavior.

Finite one-off service run

run SERVICE -- COMMAND ARG... sends one command to the authenticated foreground owner of a running authored project, which runs it in a fresh one-off container rather than inside the service's running member. The owner derives the container from the exact admitted member it inspects: the same immutable image, the member's effective environment, entrypoint, user and working directory (--workdir selects an absolute guest directory instead), the same dropped capabilities and process policy, and the member's network namespace, so the command reaches the project's other services exactly as the member does. The one-off never joins a project network as its own endpoint, never carries the service alias or canonical member name, and never registers as the service's member; ps, logs and exec continue to observe the original member. Arguments are literal, including empty arguments, spaces and shell characters; no shell is inserted. Stdin is closed and no TTY is allocated.

The owner verifies the admitted service, full resource ownership, guest boot, image, container start generation and current source/data bindings before each create, start, wait, log read and removal transport and after completion. It publishes a value-free pending record for the one-off before the create effect and discards it only after the one-off's proven removal. A one-off whose member carries mounts (live source, persistent data or private environment delivery) refuses before any effect; its container would otherwise need its own admitted bindings. An omitted command, --profile, --env, service subsets, --json, detached execution, TTY or interactive input refuse before input acquisition or any owner request. This does not start, restart or recover a project and does not acquire managed values.

One 30-second observation budget covers the identity proofs, the create, start and completion wait, a bounded log read and the forced removal. Known completion preserves the command's exit code and binary stdout/stderr, with up to 1 MiB per stream and an explicit truncation notice. A timed-out, interrupted or unproven step withholds output and keeps the one-off container and its pending record; the next whole-project down, or down --recover for a dead owner, removes every recorded one-off before it stops the canonical members, and a record whose container is already absent is discarded without effects. A recorded container whose labels do not match the exact run, review, owner and token is never removed. Cancellation settles the local request but cannot prove guest completion; once a validated completion is being written, cancellation returns 130 and prevents remaining writes. No request is replayed and the foreground project is not stopped. Portable stand-in and fake-engine controls cover the derivation, record lifecycle and reap ordering; installed native run and live application behavior remain separate gates.

Finite host lifecycle hooks

The experimental foreground frontend admits typed host.up.before, host.up.after, host.down.before and host.down.after commands. Every phase and selected host environment binding is checked before the first hook. Unsupported workload capabilities still refuse; no intent is stripped to make the graph acceptable. Normal standalone graph native plan, run and serve continue to refuse host intent. The frontend alone uses an explicit version 3 private source envelope and immutable finite-hook permit. Existing graph receipts and source version 2 keep their meanings.

up.before runs after pure native capability review. The frontend then reacquires input and managed environment selection and performs a fresh native review before starting workloads. Hook selection, project, source/worktree policy and selected profiles and authored semantic identity must remain identical. Managed bindings are reacquired without authorizing a changed workload declaration. up.after runs after authenticated native readiness; current readiness and inputs are checked again before publishing frontend readiness. The original configured startup budget includes both phases. Commands retain ordered exec/shell, cwd, environment target, unset and inherited-terminal semantics through the existing supervised shell owner.

For a ready finite-hook generation, ordinary whole-project down contacts the live foreground owner using a private per-run capability. Ctrl-C makes the same stop request. down.before must succeed before native shutdown starts; a failed phase leaves the supervisor and runtime live and cannot be replayed. A second interrupt explicitly cancels the finite hook and requests exact native cleanup. down.after runs only after authenticated native Removed and successful down.before. Down hooks have no new arbitrary duration ceiling; the shell owner supervises cancellation and process-group settlement. A down client timeout does not replay or cancel the foreground operation. Detached startup and service subsets remain unsupported; whole-project restart issues this same stop request before its fresh start. Known nonzero down.after completion reports failure after retiring the stopped generation. Unknown completion keeps the frontend bindings and hook intent together; it cannot silently make a new generation eligible.

A distinct private hook owner records intent before each phase, captured child groups and known completion after child exit and group absence. Commands, values and raw errors are never journalled. Unknown completion blocks a new generation. Explicit dead-owner recovery performs no hooks or credential acquisition: the existing native owner first proves exact Removed, and only fully completed, unchanged hook records may retire. An interrupted host phase, pre-ready hook-only attempt or ambiguous child retains evidence and requires separate resolution; no automatic hook replay or inferred completion is supplied.

Portable controls and synthetic runtime acceptance are distinct from live provider acceptance. Full NC05 corpus acceptance is still required.

Supervised host processes

The native foreground frontend also admits normalized host.processes with startup up and exit stop_on_down, using the same Hack lifecycle mux controller as the ordinary CLI. Processes start after successful up.before and remain owned through workload readiness. After exact native Removed, the frontend stops its captured process groups before down.after and retires their owner only after known stop. Startup keeps the configured startup deadline; a running process has no added duration ceiling. This slice requires tmux because its existing backend supplies the captured group identity needed for stop; zellij remains unsupported here.

An explicit private source-version5 permit binds the frontend owner, run, project, branch, semantic selection and process-owner/ready documents. Ordinary standalone native graph commands still refuse host intent. Source version3 finite hooks and native receipt versions2–5 retain their meanings. This capability refuses live-source, persistent-storage and owned-topology intersections before effects.

Commands, cwd and managed values reach the supervised client through a private one-use local socket. The mux command contains only the internal client and opaque socket path; managed values are not placed in argv, mux environment or journals. Compiler-verified HTTP(S) host-binding references resolve to loopback only for host context, or to an explicit external hostname. Workload/guest, routed and TCP references remain unsupported until their delivery owners are integrated.

Dead-owner recovery first proves the exact native Removed result, then uses the saved complete process metadata and current controller token to stop only the captured groups. A missing session requires those groups already absent; a PID alone never authorizes a signal. Changed metadata, foreign tokens or an interrupted launch without a complete ready/state pair retain evidence and cannot replay the process or hooks. Portable real-child controls do not qualify the retained Event Agent's tunnels, guest access or routing; live corpus acceptance remains open.


Source: v5 (next.12) · docs/reference/native-authored-commands.md.

On this page