Repository navigation
Conversation
A launch now starts the argv the box's spec names. Only a launch for hooks holds the shell, so the task does not run before its hooks. ensure_host replaces a hook-launched shell with the entrypoint. A task run on a task box relays the entrypoint's output from the box's log and returns the exit code the record keeps. The client leaving does not stop the box. The older sandboxed task path stays for one release, for a client that sends its arguments on the request.
The task box's spec now carries the typed arguments on its entrypoint, min task run <task> <args>. The run asks the daemon for that entrypoint, owns no box, and exits with the code it relays. The box ends with its task and stays as an exited record, and the run prints the min box rm command that removes it. An interactive task, which has no spec, keeps the exec path.
A task run on a task box returns the entrypoint's exit code 7 and its output, and the box stays as an exited record. A run whose client goes away leaves the entrypoint running, launched once. The record of an ended box is read from disk, because its actor stops with it. The owns_box request and end_run_box are marked as the older path, kept for one release.
…-as-a-task-box-that-returns-its-exit-c
|
Important Review skippedBot user detected. To trigger a single review, invoke the
|
…-as-a-task-box-that-returns-its-exit-c
The task box now keeps its record when its entrypoint returns. The e2e checks the kept line, the listing, and min box rm.
The run sends no --owns-box. The harness has no packages, so the stdin test pins the bridge's return, and the e2e pins the output.
…-as-a-task-box-that-returns-its-exit-c
|
Round 1 of 10 on a failed check suite, pushed as
Verify Outside the task's
Converted to a draft: something above needs a person before review.
Notes from the agent: Revise round 1: three failed checks. (1) native-daemon-e2e: scripts/session-e2e.sh still expected |
|
/revise The session e2e fails the same way on all three lanes at head c5c33db (native-daemon-e2e, macOS e2e, test-kvm), and passes on main. This is not a flake. In scripts/session-e2e.sh, the "task run proof (min task run: ephemeral session loop)" step fails: (native run 41899142682, macOS run 41899142453, KVM run 41899142559.) The text is |
…-as-a-task-box-that-returns-its-exit-c
ensure_host checked status != Active before it checked for a stopped or exited box, so a run on an exited task box read as still activating. The ended-box check now comes first.
A task box ends when its task returns, and only a running box can run a command. A --keep run creates its box with no spec, as an interactive task does, so min session run and an attach can use it afterwards.
…-as-a-task-box-that-returns-its-exit-c
|
Revise round 1 ran against |
|
Round 2 of 10 on a /revise note, pushed as
Verify Outside the task's
Converted to a draft: something above needs a person before review.
Notes from the agent: Directive: the diagnosis in the note does not hold. The kept box e2e-echo-1 was not activating. Its task box entrypoint returned, so the box was exited (BOX-038). ensure_host in box_actor/host.rs checked |
…-as-a-task-box-that-returns-its-exit-c
A task run that relays its box's entrypoint dropped the client's directory, so an inherit_cwd task started at /workbench. The exec now stages the directory with the task's variables, and the launch starts the argv entrypoint there, with PWD set for the in-box min task run.
The entrypoint run request now carries the invocation directory for a task that declares inherit_cwd, as the older task run request did.
|
Round 3 of 10 on a failed check suite, pushed as
Verify Outside the task's
Converted to a draft: something above needs a person before review.
Notes from the agent: Revise round 3. The one real failure was the e2e check 'inherit_cwd task did not start in sub/inner', in e2e and in native-daemon-e2e. The other failed checks are lane aggregators (ci-*-success). The test-kvm excerpt shows no failure line of its own. Cause: the entrypoint run request sent an empty cwd, and the daemon launched the entrypoint at /workbench. The in-box min helper sends $PWD, so the entrypoint must start in that directory. Fix: (1) the client sends the inherit_cwd directory on the entrypoint request (task.rs). (2) task_entrypoint_box no longer sends a request with a cwd down the older path. The entrypoint start validates the directory with task_start_dir and writes the same fallback notice to the run's output when the directory is not in the uploaded tree (process.rs). (3) entrypoint_env stages the directory beside the variables, under a reserved connection key START_DIR_KEY (host.rs). launch_host removes the key from the connection layer that the host keeps. (4) The launcher takes the key out before it builds the environment, and starts an argv entrypoint there with current_dir and PWD (box_runtime/launcher.rs). An owns_box request from a min that predates T43 still gets its destroy from exec.rs, as before. I did not run scripts/session-e2e.sh or native-daemon-e2e. They need a daemon or a VM that this box cannot run, so the inherit_cwd e2e is unverified here. The related unit tests pass: task_start_dir_honours_inherit_cwd, the env task_entrypoint tests, and the minimal task_run tests. No file outside the layers changed this round. |
|
Revise round 3 ran against |
|
/revise One e2e check is stale at head 22ee4f7. Fix the check, not the behaviour. All three e2e lanes fail at scripts/session-e2e.sh ~24074 (native run 41920526320): The run gets the earlier steps right: the task ran inside its box, and the client was SIGKILLed while the command ran. But the wait loop reads "ended" as "no longer in Under this PR, the task box keeps its record when its task returns. BOX-038 says "end the box … and retain the record". Spec 29 (the note on NET's "exists") reads NET's "exists" as the Change the wait so it passes when the run's box is listed in an ended state ( Change nothing else. |
…-as-a-task-box-that-returns-its-exit-c
A task box keeps its record when its command returns (BOX-038), so NET-131's end is the box leaving running. The wait now reads State and Exit code from min box show, passes on exited or stopped, and checks the exit code is the task's 0.
…-as-a-task-box-that-returns-its-exit-c
|
Round 4 of 10 on a /revise note, pushed as
Verify Outside the task's
Converted to a draft: something above needs a person before review.
Notes from the agent: Revise round 4: the /revise note asked for a change to scripts/session-e2e.sh. That file is outside the task's layers, but the note named it. The NET-131 wait in po_run_half now keeps the empty-listing guard on |
|
/revise The NET-131 state check now passes. Review at head 10708e8 found these. The five test and e2e files outside the layers are accepted.
Change nothing else. |
There was a problem hiding this comment.
minimal-review — approval withheld
Verdict COMMENT — APPROVE withheld: 2 unresolved threads — minimal-foundry[bot] crates/minimald/src/box_actor/host.rs:428, minimal-foundry[bot] crates/minimald/src/box_actor/host.rs:383. No findings.
Panel: 3 of 3 personas ran (correctness, security, supply-chain).
There was a problem hiding this comment.
minimal-review — approved
Verdict APPROVE — every review thread is resolved; @agent-137 closed the last one. The review of 8557f29141b7 withheld this approval on the threads open then. Posted as a comment: the App cannot approve its own pull request; the check and the label carry it.
A task run released its box's name hold, and with it the box's host_ip egress on the VM host daemon, whenever the run returned. A box the run keeps may still run (a run that lost its channel never ends it), or it ended and keeps its record until it is reaped. Its egress was cut all the same: on minvmd, `min task run long-job | head -1` lost the box's network while the task ran on. The run now releases only when it removed the box itself, and an interrupt releases only when it destroys the box. A stopped or kept box keeps both until its reap releases them. `release_task_name_hold` loses its `keep` parameter, which no caller set any more. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016CYvTvep9ZaSf5pJMB2hQA
A second `min task run` that joined a running task box's entrypoint took its streams over: the host replaced the first run's relay, so the first run got the exit code and no output, and the second got the output. The host now hands the entrypoint's streams to one run at a time. While an earlier run still reads either stream, a later take is refused, and that run exits 1 with: Task <task> is already running in box <box>, and another min task run shows its output. Only one run at a time can show a task's output. A run whose client went away closed its streams, so a later run still takes them in its place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016CYvTvep9ZaSf5pJMB2hQA
A task run's resolved variables, which can hold values from the caller's shell and secrets among them, reached the launch that starts the box's entrypoint as connection variables. The host kept those for the box, so every later `min exec` in the box saw them, and the box's environment held them too. They now ride a launch field of their own, which the launcher sets on the argv entrypoint's process only. Neither the box's environment nor the host's connection layer holds them, so no later exec, attach or hook in the box sees them. The start directory rides there as well. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016CYvTvep9ZaSf5pJMB2hQA
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016CYvTvep9ZaSf5pJMB2hQA
There was a problem hiding this comment.
arch-review: CONDITIONS · 1 condition · the full ruling
The four commits conform to lines 499 and 501, and the compare keeps the earlier PASS except for one point. A second min task run that finds the entrypoint relayed by another run exits 1. Line 363 gives exit 2 to an exec against a box in the wrong state, with the holder or the state named. Exit 1 is also the code that a failed task most often returns, so a script cannot tell the two apart. Make the change in C1.
Ruled at 0b31489 against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016CYvTvep9ZaSf5pJMB2hQA
There was a problem hiding this comment.
arch-review: PASS · the full ruling
The compare makes one change. A second min task run that joins an entrypoint that another run relays now exits 2. Before, it exited 1. Exit codes line 362 gives 2 to an operation that the target's state does not admit. The refusal names the box and its state. This meets C1 from the ruling on 0b31489b. The rest of the change keeps its PASS from 8557f291.
Ruled at 5c6c53b against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.
There was a problem hiding this comment.
minimal-review — approval withheld
Verdict COMMENT — APPROVE withheld: 4 unresolved threads — minimal-arch[bot] crates/minimald/src/exec/process.rs:878, minimal-arch[bot] crates/minimald/src/box_actor/tests.rs:16711, minimal-foundry[bot] crates/minimald/src/box_actor/host.rs:1550, minimal-foundry[bot] crates/minimal/src/cli.rs:991. No findings.
Panel: 3 of 3 personas ran (correctness, security, supply-chain).
There was a problem hiding this comment.
minimal-review — approved
Verdict APPROVE — every review thread is resolved; @agent-137 closed the last one. The review of 5c6c53b7b12b withheld this approval on the threads open then. Posted as a comment: the App cannot approve its own pull request; the check and the label carry it.
There was a problem hiding this comment.
Babysitter review of 5c6c53b against T43's plan block and the fix round (not an approval; the owner approves this head). D1: a second task run is refused while the first relays the task, and exits 2 (arch C1). C1: a kept task box keeps its name hold and egress until its reap. D6: staged task variables reach only the entrypoint. All 8 bot-resolved threads re-checked on this head. Required lanes are green and arch passes. Follow-ups: #3077 (hook-shell refusal), and D2, C3 and the review nits to be filed after merge.
T43 — Run a task as a task box that returns its exit code
slice: S2
kind: task
covers: BOX-015, BOX-038
size: L
est: 440 code, 300 tests
executor: agent
difficulty: needs care
model: strongest
diagnostics: daemon log names each task box and its code
observability: one span per task run
layers:
- client:
- crates/minimal/src/task.rs: task box from spec; exit code
- crates/minimal/src/cmd/boxes/create.rs: shared create path
- crates/minimal/src/cmd/boxes/lifecycle.rs: run keeps its box
test: cargo nextest run -p minimal task_run_returns_the_entrypoint_exit_code
- daemon:
- crates/minimald/src/exec/run.rs: old task path, one release
- crates/minimald/src/exec/process.rs: task is the entrypoint
- crates/minimald-rpc/src/exec.rs: old request, one release
- crates/minimald/src/box_actor/host.rs: launch runs the spec argv; drop run_by_exec
- crates/minimald/src/box_runtime/launcher.rs: entrypoint launches the argv, not the shell
test: cargo nextest run -p minimald daemon_never_stops_for_idle_or_client_loss
test: cargo nextest run -p minimald until_complete_ends_on_entrypoint_return_without_client
produces: none
consumes: none
proof:
min task runreturns the exit code and keeps the box.depends on:
- blocked by #2401
- blocked by #2398
- blocked by #2953
Proof
min task run <task>now creates a task box whose entrypoint ismin task run <task> <args>. The daemon starts that entrypoint, relays its output, and the command exits with the entrypoint's exit code. The box ends with its task and stays as an exited record with that code, whichmin box listshows. The command then printsKept box <name>. Remove it with min box rm <name>.Notes from the agent: Design: a launch now starts the spec argv. Only a hook launch holds the shell (
LaunchSpec::run_by_execis nowfor_hooks).ensure_hostreplaces a hook-launched shell with the entrypoint, but not for a box that holds a host-side row: that case refuses the run at once with a message saying why, and the client removes the box (no "Kept box" line). ATaskRunexec on a task box (spec entry is the task, entrypoint is an argv, no args, no cwd) relays the entrypoint: output from the box log with CR LF turned back to LF, and the exit code from the on-disk record. The client leaving stops the relay, not the box (BOX-015). Any otherTaskRuntakes the old sandboxed path: an interactive task has no spec, so it runs over the exec channel withowns_boxset and ends its box with the run.min task run --keepis removed (maintainer ruling: the architecture has no--keep, and BOX-038 keeps every record). Observability: spantask_run(box_id, box_name, task) on the daemon and on the client. Diagnostics: daemon log linetask box endedwith box_id, box_name, task and exit_code.Gaps, all from scope: (1) The resolved task variables reach the entrypoint launch through a staging seam in box_actor/host.rs (
entrypoint_env), keyed by box id, because the actor's EnsureHost message (box_actor.rs, handle.rs) carries no environment and is outside the layers.[vars] ignoredrops are not applied on the new path. (2)inherit_cwdis honoured: the start directory reaches the entrypoint launch only. (3) The entrypoint runs on three pipes, so the task's stdout and stderr come back as two streams. Spec 28 still describesmin task run --keep(BCLI-042 lists it as an alias); its amendment is #3036.Residual
min task rundoes not pass its stdin to the task yet. The task box's entrypoint is the in-boxmin task runhelper. It sends its run request over the box's minenv socket and forwards no stdin, so the task reads none.min task run --helpsays so (c1833fc). Forwarding stdin changes the minenvrunprotocol and the daemon's in-box task-run path, and adds an e2e stdin step. It is owned by T123 — A piped stdin reaches a task box's task #3055 (T123).Tests
cargo nextest run -p minimal task_run_returns_the_entrypoint_exit_codecargo nextest run -p minimald daemon_never_stops_for_idle_or_client_losscargo nextest run -p minimald until_complete_ends_on_entrypoint_return_without_clientVerify
min task run agent-verifytimed out after 1800s, so this PR is a draft.Base
The base branch moved while the coder worked; it was merged in before the tests ran.
Out of scope
These files are outside the task's
layers:, so this PR is a draft:crates/minimald/src/box_actor/tests.rscrates/minimald/src/box_runtime/tests.rsCloses #2405