Repository navigation
Description
Task
| slice | size | difficulty | model | who | estimated lines |
|---|---|---|---|---|---|
| One minimal.toml for every box | M | needs care | standard | an agent | 330 (120 code, 210 tests) |
A box whose spec sets
hooks_on_resume = truerunson_activateagain when it resumes. A box without the key runs onlyon_attach.
Covers:
- BOX-028
Layers:
- daemon:
- crates/minimald/src/box_actor.rs:
resume_endedruns the box'son_activatehooks after it writes the recordrunningand before it returns. It does so only when the stored spec it already loads (object.load_spec(), thenbox_runtime::stored_spec) setsexecution.hooks_on_resume = trueand the box runs its hooks (hooks_enabled,has_hooks_for(HookEvent::Activate)). It launches the hooks host as activation does in crates/minimald/src/box_actor/setup.rs (launch_host_for_hooks(LaunchPhase::Activating), thenhelpers::run_session_hooks(.., HookEvent::Activate)), soon_activateruns before the attach's launch runson_attach, in the same order as at activation. A failed hook writes back the record the resume read, asfinish_resumedoes when a launch fails, then marks the name stopped, releases the name claim and refuses the resume.finish_resume's BOX-027 comment names the BOX-028 exception - crates/minimald/src/box_actor/tests.rs: tests
cargo nextest run -p minimald hooks_on_resume_reruns_on_activatecargo nextest run -p minimald hooks_on_resume_failing_on_activate_refuses_resume_keeps_statecargo nextest run -p minimald resume_runs_only_on_attach_hook
- crates/minimald/src/box_actor.rs:
- config:
- crates/mfile/src/lib.rs:
warn_unknown_fieldsdoes not reporthooks_on_resumeas unknown in[session]or[tasks.<name>] - crates/mfile/src/spec.rs: the
BoxSpec::hooks_on_resumedoc comment saysminimaldreads the key at resume (BoxActor::resume_ended) and runson_activateagain (added per arch ruling 1044, C2) cargo nextest run -p mfile hooks_on_resume_entry_key_is_not_reported_unknown
- crates/mfile/src/lib.rs:
- docs:
- docs/reference/minimal-dot-toml.md: the
hooks_on_resumekey under[session]and[tasks.*]
- docs/reference/minimal-dot-toml.md: the
Split from T20 (#2415) by the owner's decision after arch's ruling on PR #3104. The ruling found that T20's hooks layer named the wrong file. crates/minimald/src/hooks.rs says in its module doc that it does not decide when hooks fire. The resume decision is in crates/minimald/src/box_actor.rs resume and resume_ended, and activation hooks run from crates/minimald/src/box_actor/setup.rs and helpers::run_session_hooks. The ruling's words: run on_activate again in box_actor.rs resume / resume_ended when the stored spec sets execution.hooks_on_resume = true. T20's other half, the timeout (BOX-037), is T64.
depends on: PR #3104 (T20 spec layer). That PR adds BoxSpec::hooks_on_resume, serialized as execution.hooks_on_resume and read from the entry table. This task only reads the field from the stored spec.
The decision reads the spec stored at creation (BOX-025, BOX-068), not the project's current minimal.toml. Setting the key in minimal.toml after a box was created therefore has no effect on that box. The test checks that too.
hooks_on_resume_reruns_on_activate creates a session whose stored spec sets hooks_on_resume = true and whose on_activate appends a line to a marker file. It is a copy of resume_runs_only_on_attach_hook with session_with_hook taking the spec. The test stops the box through the daemon, attaches to resume it, and checks that the marker holds two lines. It does the same for an exited box. The existing resume_runs_only_on_attach_hook (BOX-027) stays as it is and must still pass: without the key, the marker keeps one line. hooks_on_resume_failing_on_activate_refuses_resume_keeps_state makes the hook fail on its second run only. It checks that the attach is refused with the text below, and that the record stays in the state it resumed from (assert_resume_refused). It also checks that no resumed event is written, and that a later attach after the hook is fixed resumes the box.
User-facing text. One new refusal, printed by the min session attach that would resume the box. It is an error that ends the command, so the rule about lines before the box shell does not apply. It uses the prefix every resume refusal in resume_ended uses (the refused closure):
session `dev` cannot resume, and it stays stopped. Its activation hook from user loadout `dev` exited with status 3. Fix the hook, then attach again with `min session attach dev`.
The hook printed:
ACTIVATE_SAID_NO
The format string is session {name}cannot resume, and it stays {from}. Its activation hook from {declared_by} {status}. Fix the hook, then attach again withmin session attach {name}., followed by \nThe hook printed:\n{output} only when the hook printed something. {declared_by} and {status} are HookOutcome::declared_by and the Display of its status in crates/minimald/src/hooks.rs, which the activation failure in setup.rs already prints (exited with status 3, was killed by a signal, timed out after 30s). The text is true because resume_ended writes back the record before it refuses, so the box stays stopped or exited. hooks_on_resume_failing_on_activate_refuses_resume_keeps_state pins the whole text. The existing a_failing_activate_hook_blocks_the_session pins the activation wording, which does not change.
On a healthy resume this task adds no line before the box shell. The hooks' outcomes go to the daemon log.
The refusal exits 1 (the ResumeRefused status), the owner's decision: the other resume refusals exit 2 (terminal, name) or 3 (stored spec), and neither fits a failed hook. hooks_on_resume_failing_on_activate_refuses_resume_keeps_state pins the exit code with the text.
Observability: the box.resume span gains a hooks_on_resume field (true or false) and the count of activation hooks run. The daemon log line is resume: ran on_activate again (hooks_on_resume), with box_id and the outcomes, as activation logs them.
Waits on:
Plan block
### T65 — Run on_activate again when a box resumes, if its spec sets hooks_on_resume
slice: S4
kind: task
covers: BOX-028
size: M
est: 120 code, 210 tests
executor: agent
difficulty: needs care
model: standard
diagnostics: daemon log names each on_activate run on resume and its outcome; a failed hook refuses the resume naming the hook's source and status
observability: box.resume span records hooks_on_resume and the activation hooks run
layers:
- daemon:
- crates/minimald/src/box_actor.rs: resume_ended runs on_activate when the stored spec sets execution.hooks_on_resume; a failed hook restores the record and refuses
- crates/minimald/src/box_actor/tests.rs: tests
test: cargo nextest run -p minimald hooks_on_resume_reruns_on_activate
test: cargo nextest run -p minimald hooks_on_resume_failing_on_activate_refuses_resume_keeps_state
test: cargo nextest run -p minimald resume_runs_only_on_attach_hook
- config:
- crates/mfile/src/lib.rs: hooks_on_resume is not an unknown key
- crates/mfile/src/spec.rs: hooks_on_resume doc says minimald reads it at resume
test: cargo nextest run -p mfile hooks_on_resume_entry_key_is_not_reported_unknown
- docs:
- docs/reference/minimal-dot-toml.md: hooks_on_resume key under [session] and [tasks.*]
produces: none
consumes:
- crates/mfile/src/spec.rs
proof: A box whose spec sets hooks_on_resume = true runs on_activate again when it resumes; a box without the key runs only on_attach.
depends on:
- blocked by #2415
Activity
minimal-foundry commentedon Nov 7, 2026
Pull request #3123 is open for T65.
branch
agent/3111-run-on-activate-again-when-a-box-resumes-if-its· epic #223623bedd27b056e8ee3d2849181b3fc31acargo nextest run -p minimald hooks_on_resume_reruns_on_activatecargo nextest run -p minimald hooks_on_resume_failing_on_activate_refuses_resume_keeps_statecargo nextest run -p minimald resume_runs_only_on_attach_hookcargo nextest run -p mfile hooks_on_resume_entry_key_is_not_reported_unknownVerify
min task run agent-verify: exit 101 — the sandbox ran rustc (1.99.0), the repository pins 1.99.1 in rust-toolchain.toml; a failure here may be the newer toolchain's, not this change's ecking sendfd v0.4.4 Checking caps v0.5.6 Checking close_fds v0.3.2 Checking crossbeam-channel v0.5.16 Checking ssh-encoding v0.3.0 ChUpdated 2026-11-07T18:21:21.751Z.