8000 T65 — Run on_activate again when a box resumes, if its spec sets hooks_on_resume · Issue #3111 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

T65 — Run on_activate again when a box resumes, if its spec sets hooks_on_resume #3111

Open

Description

@agent-137

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 = true runs on_activate again when it resumes. A box without the key runs only on_attach.

Covers:

  • BOX-028

Layers:

  • daemon:
    • crates/minimald/src/box_actor.rs: resume_ended runs the box's on_activate hooks after it writes the record running and before it returns. It does so only when the stored spec it already loads (object.load_spec(), then box_runtime::stored_spec) sets execution.hooks_on_resume = true and 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), then helpers::run_session_hooks(.., HookEvent::Activate)), so on_activate runs before the attach's launch runs on_attach, in the same order as at activation. A failed hook writes back the record the resume read, as finish_resume does 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_activate
    • cargo nextest run -p minimald hooks_on_resume_failing_on_activate_refuses_resume_keeps_state
    • cargo nextest run -p minimald resume_runs_only_on_attach_hook
  • config:
    • crates/mfile/src/lib.rs: warn_unknown_fields does not report hooks_on_resume as unknown in [session] or [tasks.<name>]
    • crates/mfile/src/spec.rs: the BoxSpec::hooks_on_resume doc comment says minimald reads the key at resume (BoxActor::resume_ended) and runs on_activate again (added per arch ruling 1044, C2)
    • cargo nextest run -p mfile hooks_on_resume_entry_key_is_not_reported_unknown
  • docs:
    • docs/reference/minimal-dot-toml.md: the hooks_on_resume key under [session] and [tasks.*]

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

  1. added
    kind:taskA task the plan skill rendered; the body carries ## Task
    size:M200 to 500 net lines; one PR
    model:standardA standard model: work that needs care, or routine work that is large
    on Nov 6, 2026
  2. minimal-foundry commented on Nov 7, 2026

    @minimal-foundry
    Contributor

    Pull request #3123 is open for T65.

    branch agent/3111-run-on-activate-again-when-a-box-resumes-if-its · epic #2236

    round outcome job
    1 pushed 23bedd27
    2 pushed b056e8ee
    3 pushed 3d284918
    4 pushed 1b3fc31a
    test exit tail
    cargo nextest run -p minimald hooks_on_resume_reruns_on_activate 101 warning: unknown fields in [defaults] section of minimal.toml: session,task help: do you need to update to a newer version of minimal? Applying loadouts: default Running task runtime-implement-test-0 in box runtime-implement-test-0-1... error: no such command: 'nextest' help: a command with a simil
    cargo nextest run -p minimald hooks_on_resume_failing_on_activate_refuses_resume_keeps_state 101 warning: unknown fields in [defaults] section of minimal.toml: task,session help: do you need to update to a newer version of minimal? Applying loadouts: default Running task runtime-implement-test-1 in box runtime-implement-test-1-1... error: no such command: 'nextest' help: a command with a simil
    cargo nextest run -p minimald resume_runs_only_on_attach_hook 101 warning: unknown fields in [defaults] section of minimal.toml: task,session help: do you need to update to a newer version of minimal? Applying loadouts: default Running task runtime-implement-test-2 in box runtime-implement-test-2-1... error: no such command: 'nextest' help: a command with a simil
    cargo nextest run -p mfile hooks_on_resume_entry_key_is_not_reported_unknown 101 warning: unknown fields in [defaults] section of minimal.toml: task,session help: do you need to update to a newer version of minimal? Applying loadouts: default Running task runtime-implement-test-3 in box runtime-implement-test-3-1... error: no such command: 'nextest' help: a command with a simil

    Verify 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 Ch

    Updated 2026-11-07T18:21:21.751Z.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:taskA task the plan skill rendered; the body carries ## Taskmodel:standardA standard model: work that needs care, or routine work that is largesize:M200 to 500 net lines; one PR

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0