Skip to content

fix(core): let the service decide a resume past the suspended window (#597) - #601

Merged
laithalsaadoon merged 8 commits into
mainfrom
fix/resume-explicit-suspend-window
Oct 12, 2026
Merged

laithalsaadoon merged 8 commits into
mainfrom
fix/resume-explicit-suspend-window

Conversation

@laithalsaadoon

@laithalsaadoon laithalsaadoon commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

What and why

Sandbox::resume refused with ERR_WINDOW_CLOSED once suspendedDurationSeconds had passed since the sandbox's own suspend(). It refused before any call to the service, in require_open_suspended_window (crates/microvms-app/src/sandbox.rs, STATE-12). The service didn't apply that window to an explicit suspend. On 2026-10-12 in us-east-1, two VMs with maxIdleDurationSeconds 60 and suspendedDurationSeconds 60, suspended with SuspendMicrovm, were still SUSPENDED 906 and 917 seconds later, and ResumeMicrovm brought both to RUNNING; a third, with a 3600-second idle limit, resumed after 1283 seconds. So the client refused resumes that the service would have honored. AWS's IdlePolicy reference describes the window for any suspended VM, so the explicit case is measured behavior AWS doesn't promise, and the client now depends on neither answer: the service decides. The window does end a VM that the idle policy suspended. That VM was TERMINATED about 60 seconds after it suspended, and ResumeMicrovm then returned a ValidationException saying the VM "has been terminated and its state cannot be changed."

Before this change, a resume past the window of the sandbox's own suspend failed with ERR_WINDOW_CLOSED before any call, even though the service would have resumed the VM. After it, every resume goes to the service, and ERR_WINDOW_CLOSED reports a resume the service refused for a VM that had already ended, whatever ended it.

  • Sandbox::resume no longer records when it suspended the VM, and it doesn't check a window. The suspended_at field and require_open_suspended_window are removed.
  • ControlPlane::resume (crates/microvms-app/src/control/microvm.rs) reads the VM with GetMicrovm when the service refuses a resume with a 400. If the VM is TERMINATING or TERMINATED, the error becomes ERR_WINDOW_CLOSED, its message names the state and stateReason, and the service's refusal is its source. The message names no cause and says to launch a new VM, because a VM a terminate ended gets the same refusal as one the service ended. For any other state, or when the read fails, the caller gets the service's own error. The check reads the VM's state and doesn't match the message text.
  • The CLI resume command and both bindings' ControlPlane.resume call ControlPlane::resume, so they get the same mapping. microvm resume on an ended VM now exits 8 (ERR_WINDOW_CLOSED). Before this change it exited 9 (ERR_PLATFORM). The changelog fragment says so.
  • After a WindowClosed refusal, the sandbox records the VM as TERMINATED and as terminated, so a second resume is refused before any call (STATE-11). A refusal for a VM that's still alive leaves the sandbox SUSPENDED, and the next resume goes to the service again.
  • A Sandbox doesn't see a suspend the idle policy makes, so it still holds that VM as RUNNING and its resume is refused before any call (STATE-7), as on main. The docs say so, and say the suspend reaches a caller only through Sandbox::adopt or ControlPlane::resume. The Drop warning names the state as the one the sandbox last saw, and says only that a VM that's still live bills.
  • STATE-12 in verify/spec/core.symspec.json now says the client issues the resume and reports the service's refusal for an ended VM as a window-closed error. The client model in crates/model/src/client.rs drops its clock. It gains a SuspendedVmEnded action, which is the platform ending a suspended VM, and a resume of that VM reaches the service and is refused. The model-conformance test replays the new paths against Sandbox.
  • Every surface that stated the old rule now states the new one:
    • the --suspended-sec help on both commands, the resume command doc, and the ERR_WINDOW_CLOSED exit meaning and hint, which now says the VM ended before the resume (the suspended window, the maximum duration, or a terminate) and names no flag;
    • crates/microvms-cli/README.md and the WindowClosed doc in microvms-domain;
    • the WindowClosedError, ControlPlane.resume, and Sandbox docs in both bindings, with microvms.pyi and index.d.ts regenerated;
    • the module docs of crates/microvms-app/src/clock.rs, which described the window timing this change removes;
    • docs/manifest.json, docs/reference/cli.md, docs/insights/debugging-guide.md, and docs/insights/contract-map.md;
    • three pages under site/authored/learn/operations/ and the long-lived VM tutorial, which also say that ERR_WINDOW_CLOSED for an idle-suspended VM comes from microvm resume and ControlPlane.resume, and that a Sandbox refuses its own resume first (A Sandbox never sees a platform idle suspend, so resume refuses from RUNNING #603);
    • docs/behavior/processes.md, whose suspend and resume steps described the stamp and window check this change removes.

Verified offline only. No live run exercises this change.

Size: 841 changed lines of product code. 515 of them are unit tests, almost all in sandbox.rs and control/microvm.rs. They replace the STATE-12 tests that held the old rule and add the refusal tests. The other 326 lines are the fix and the doc comments that stated the old rule on each surface. If the docs were split from the fix, one pull request would ship docs that contradict the code.

Fixes #597

Evidence

  • feat(example): Codex SDK in a Strands Box on a MicroVM, on bedrock-runtime #594 and docs: one current answer per platform fact, and a prose rule that holds it #598 merged as 944577f and f410ec2, and this branch is rebased onto main f410ec2 and targets main. On 4384885 (head), 2026-10-12:
    • mise run check exits 0: 1,804 Rust tests passed, 0 failed, 28 ignored; prose 0 errors, 4,084 warnings, under every ceiling; guards:list 1,333 faults.
    • mise run docs:check exits 0: 223 site tests, CSpell 0 issues.
    • 54af2d9 makes the help, CLI reference, changelog and site text say the explicit-suspend result is measured and not promised, and fixes processes.md. Because each FAIL_TO_PASS patch reverses every product hunk, 4384885 regenerates the six patches with fail-to-pass.py's fix_patch against f410ec2. guards:fire then fired 7 of 7 (the six entries and resume-window-closed-drops-the-refusal).
  • The review fixes are 19bd74a (the ERR_WINDOW_CLOSED message and meaning), ecd4d60 (what a Sandbox sees of an idle suspend, and the Drop warning) and 0499612 (clock.rs's docs). On 0499612:
    • mise run check exits 0 in 301 s on 2026-10-12. cargo test --all reports 1804 passed, 0 failed, and 28 ignored. prose:check reports 0 errors and 4,080 warnings, under every ceiling, and guards:list reports 1333 faults registered.
    • mise run ci:mutants -- --base 3330dc6 -- --in-place tested the 12 mutants in the fixes' lines: 9 caught, 3 unviable, 0 missed. Over the whole diff, with --base origin/docs/one-current-fact, it tested 16: 12 caught, 4 unviable, 0 missed.
    • mise run guards:fire fires the new fault and the six FAIL_TO_PASS entries, 7 of 7; Guards has the output.
    • microvms.pyi, index.d.ts and docs/manifest.json are regenerated with mise run stubs, mise run dts and mise run manifest, and check runs stubs:check, dts:check and manifest:check.
    • bindings:py, bindings:js and docs:check weren't run again after the fixes. The fixes change the bindings' doc comments and the WindowClosedError docstring, and no binding code.

Before the review fixes:

Parity

  • No public name changed on any surface (core, CLI commands, microvms.pyi, index.d.ts).
  • mise run parity:check passes. The resume and resume-by-id rows in verify/parity/capabilities.toml don't change, because the behavior lives in core's ControlPlane::resume, which every surface calls.

No parity case covers the refusal, because the Python and TypeScript parity runners can't script a control plane.

Guards

mise run fail-to-pass -- --emit resume-window ran against the merge base 78e5f1d. It proves six tests, which fail with the fix taken out and pass with it in. It wrote their entries into verify/guards/faults/resume-window.toml with their patches. Each patch reverses every product hunk of the branch, so the review fixes regenerate all six with the script's own fix_patch against 78e5f1d, and all six fire again on 0499612's tree.

fired: f2p-a-resume-of-a-vm-the-service-ended-exits-window-closed (26.5 s)
fired: f2p-every-walked-path-of-the-client-model-replays-against (9.8 s)
fired: f2p-a-resume-refused-for-a-vm-that-terminated-while (12.5 s)
fired: f2p-an-adopted-vm-resumes-past-the-reported-window-through (7.3 s)
fired: f2p-a-resume-past-the-window-of-an-explicit-suspend-reaches (5.6 s)
fired: f2p-a-resume-the-service-refuses-for-an-ended-vm-is-window (6.0 s)

The fire on 0499612, after the review fixes, with the new hand-written fault:

guards: tree 0499612 plus 0 uncommitted paths
fired: resume-window-closed-drops-the-refusal (10.5 s)
fired: f2p-a-resume-of-a-vm-the-service-ended-exits-window-closed (18.2 s)
fired: f2p-every-walked-path-of-the-client-model-replays-against (5.8 s)
fired: f2p-a-resume-refused-for-a-vm-that-terminated-while (8.8 s)
fired: f2p-an-adopted-vm-resumes-past-the-reported-window-through (4.0 s)
fired: f2p-a-resume-past-the-window-of-an-explicit-suspend-reaches (3.8 s)
fired: f2p-a-resume-the-service-refuses-for-an-ended-vm-is-window (3.8 s)
guards: 7 of 7 fired (78.8 s of faults)
  • sandbox::tests::a_resume_past_the_window_of_an_explicit_suspend_reaches_the_service_and_resumes is the regression test for core: resume refuses an explicitly suspended VM past suspendedDurationSeconds, which the service still resumes #597. It suspends with a 60-second window and advances the clock 1283 seconds. The resume then reaches the service and succeeds.
  • sandbox::tests::an_adopted_vm_resumes_past_the_reported_window_through_the_service replaces the test that refused an adopted VM's resume past its reported window.
  • sandbox::tests::a_resume_the_service_refuses_for_an_ended_vm_is_window_closed_and_recorded checks the ERR_WINDOW_CLOSED error, the TERMINATED state, and that a second resume is refused before any call.
  • control::microvm::tests::a_resume_refused_for_a_vm_that_terminated_while_suspended_is_window_closed checks the mapping for both TERMINATING and TERMINATED.
  • control::microvm::tests::a_resume_refused_for_a_vm_a_terminate_ended_names_no_cause_and_keeps_the_refusal checks a VM a terminate ended (stateReason "Success."): the exact message, which names no cause and doubles no period, and the service's refusal as the error's source.
  • guards::history::a_resume_of_a_vm_the_service_ended_exits_window_closed_and_records_no_resume checks that the CLI exits 8 and records no resume.
  • every_walked_path_of_the_client_model_replays_against_the_sandbox replays the model's new STATE-12 paths.

Three new tests pass with the fix taken out, so FAIL_TO_PASS doesn't claim them. They are a_resume_refused_for_a_live_or_unreadable_vm_keeps_the_services_answer, a_resume_denied_for_its_credentials_reads_no_state, and a_resume_refused_for_a_live_vm_leaves_the_sandbox_suspended_and_resumable. They hold behavior that main already had.

Five hand-written faults, each fired with mise run guards:fire -- --only <id>:

  • model-client-state-12-refused-resume-unrecorded is new in verify/guards/faults/agentd-model.toml. It leaves the model's VM SUSPENDED after the service refuses a resume for an ended VM, and the property "STATE-12 a resume refused for an ended VM leaves it TERMINATED and recorded terminated" fails. It printed fired: model-client-state-12-refused-resume-unrecorded.
  • model-client-state-12-resume-refused-locally is new in the same file. It puts the removed check back into the model, so the client refuses a resume from SUSPENDED for a VM the platform ended. The property "STATE-12 a resume from SUSPENDED reaches the service" fails. It printed fired: model-client-state-12-resume-refused-locally.
  • model-conformance-client-resume-resends-payload in verify/guards/faults/model-conformance-client.toml now anchors on the new resume block. The fault sends the run hook's payload again after a resume, and the replay reports "run-hook payloads: sandbox 2, model 1". It printed fired: model-conformance-client-resume-resends-payload.
  • model-conformance-client-skips-moved in the same file now anchors on the planner's remaining skip, because the planner no longer skips a closed window. The fault stops skipping a completion that arrives after another step, and the planner fails on the pinned skip set before it replays anything. It printed fired: model-conformance-client-skips-moved.
  • resume-window-closed-drops-the-refusal is new in verify/guards/faults/resume-closed-window.toml. It removes the .with_source(refused) that attaches the service's refusal, and the terminate test fails on "the refusal is the source". It printed fired: resume-window-closed-drops-the-refusal.

After each fire, the tool printed "restored, every command passes again". verify/guards/unregistered.txt loses two lines. One is the replaced an_adopted_vm_refuses_a_resume_past_the_reported_window. The other is the_lifecycle_watch_follows_every_transition, which had a STATE-12 note attached by mistake and no longer carries it.

Follow-ups

  • A live conformance check for STATE-12 would suspend a VM through the idle policy, wait past the window, and expect ERR_WINDOW_CLOSED with the state from GetMicrovm. It would also resume an explicit suspend past its window. verify/spec/traced/STATE.toml waives the live check until the suite runs one.
  • A parity case for the window-closed refusal can be added once the Python and TypeScript parity runners can script a control plane.
  • mise run spec:core fails on main because of the word "never" in TRAP-4. This change doesn't touch TRAP-4.
  • A Sandbox whose VM the idle policy suspended still holds it as RUNNING, so Sandbox::resume refuses from RUNNING with ERR_INVALID_ARG (STATE-7) and never asks the service. That's main's behavior, and this change only documents it; A Sandbox never sees a platform idle suspend, so resume refuses from RUNNING #603 tracks it.

Platform claims

This changes claims about AWS behavior in the CLI help, the CLI README, the binding docs, the debugging guide, three site operations pages, and the long-lived VM tutorial. docs/PLATFORM.md carries the same measurement through #598, merged as f410ec2. The claims come from the measurement in #597. It was taken on 2026-10-12 in us-east-1 against API version 2025-09-09, with one VM per case and autoResumeEnabled set to false.

  • An idle-triggered suspend, with maxIdleDurationSeconds 60 and suspendedDurationSeconds 60, left the VM TERMINATED about 60 seconds after it suspended. Its stateReason was "MicroVM exceeded maximum lifetime." ResumeMicrovm then returned a ValidationException saying the VM "has been terminated and its state cannot be changed."
  • An explicit SuspendMicrovm within 10 seconds of RUNNING, on two VMs with the idle case's own policy (maxIdleDurationSeconds 60, suspendedDurationSeconds 60), left both SUSPENDED 906 and 917 seconds later with stateReason null. ResumeMicrovm was accepted, and both were RUNNING within 20 seconds. A review of docs: one current answer per platform fact, and a prose rule that holds it #598 asked for this run, because the first explicit-suspend VM had maxIdleDurationSeconds 3600; that VM was SUSPENDED 1283 seconds later and resumed too.
  • AWS's IdlePolicy reference describes suspendedDurationSeconds as the longest a MicroVM can remain suspended, with no exception for an explicit suspend, so the help and docs call the explicit case measured behavior AWS doesn't promise.
  • About 4 hours later, GetMicrovm still answered TERMINATED for the idle-suspended VM and for one ended with microvm terminate (stateReason "Success."), and ResumeMicrovm refused both with the same ValidationException. So the refusal doesn't say what ended a VM, and ERR_WINDOW_CLOSED names no cause.
  • The 2026-09-23 sample in docs/PLATFORM.md agrees. That VM was explicitly suspended with a 60-second window and was still SUSPENDED at 240 seconds.

Scope

  • This is not an orchestrator or a fork implementation
    (see docs/STRATEGY.md).

laithalsaadoon added a commit that referenced this pull request Oct 12, 2026
CI's mutation testing on #601 found both arms of classify's suggestion match
unguarded: deleting (Exit::LaunchDied, _) or (Exit::WindowClosed, _) left every
test passing. The test asserts each exit's suggestion. Locally, the change's 13
mutants against origin/docs/one-current-fact: 9 caught, 4 unviable, 0 missed.
@laithalsaadoon
laithalsaadoon force-pushed the docs/one-current-fact branch 2 times, most recently from aa5c8c8 to e60b136 Compare October 12, 2026 20:59
Sandbox::resume refused with ERR_WINDOW_CLOSED before any call once
suspendedDurationSeconds had passed since the sandbox's own suspend()
(require_open_suspended_window, STATE-12). The service doesn't hold an
explicit suspend to that window: measured 2026-10-12 in us-east-1, API
2025-09-09, a VM suspended with SuspendMicrovm and a 60 s window was
still SUSPENDED 1283 s later, and ResumeMicrovm brought it to RUNNING.
The window ends a VM the idle policy suspended, and ResumeMicrovm then
answers ValidationException "has been terminated and its state cannot
be changed."

Sandbox::resume no longer keeps a suspend time or checks a window, and
every resume goes to the service. ControlPlane::resume reads the VM with
GetMicrovm after a 400 refusal: TERMINATING or TERMINATED is
ERR_WINDOW_CLOSED naming the state and stateReason, and any other
answer, or a failed read, keeps the service's error. The CLI resume and
both bindings' ControlPlane.resume share it, so `microvm resume` on an
ended VM exits 8 (ERR_WINDOW_CLOSED) where it exited 9 (ERR_PLATFORM).
After a WindowClosed refusal the sandbox records the VM TERMINATED and
terminated, so the next resume is refused before any call (STATE-11); a
refusal for a live VM leaves it SUSPENDED.

STATE-12, the client model and its conformance replay state the new
rule: the platform ends a suspended VM as its own action, and a resume
of an ended VM reaches the service and comes back refused. The
--suspended-sec help, the resume and exit-code docs, the CLI README,
the WindowClosed docs in the domain crate and both bindings, the
generated stubs and manifest, and the debugging guide, contract map,
CLI reference and three operations pages change with it.

Verified offline only: no live run.

Fixes #597
The CLI's `guards::parity::the_cli_answers_the_shared_case_corpus_against_its_fakes` spawns
microvms-core's `parity-tunnel-peer` example from the test binary's target directory. A mutant's
`cargo test -p microvms-cli` never builds another package's example, so a change with mutants in
microvms-cli failed cargo-mutants' unmutated baseline (exit 4, "build the fixture with mise run
parity:fixtures"), as shard 3 of 4 did on #600. `ci:mutants` now depends on `parity:fixtures`,
which builds the example into the target the `--in-place` run tests from. Shard 3 of 4 run
locally with this: baseline ok in 31 s build + 9 s test, 1 mutant, unviable.
CI's mutation testing on #601 found both arms of classify's suggestion match
unguarded: deleting (Exit::LaunchDied, _) or (Exit::WindowClosed, _) left every
test passing. The test asserts each exit's suggestion. Locally, the change's 13
mutants against origin/docs/one-current-fact: 9 caught, 4 unviable, 0 missed.
ControlPlane::resume maps a refused resume of a VM that GetMicrovm reports
TERMINATING or TERMINATED to ERR_WINDOW_CLOSED. Its message said the VM
"terminated while suspended" and named the suspended window as the cause,
but the mapping only knows the VM is dead. Measured 2026-10-12 in
us-east-1: a VM ended with `microvm terminate` (stateReason "Success.")
and one the service ended (stateReason "MicroVM exceeded maximum
lifetime.") both still read TERMINATED about 4 h later, and ResumeMicrovm
refused both with the same ValidationException. So a VM the user
terminated, or one that hit its maximum duration while RUNNING, exited 8
with a false cause and a --suspended-sec remedy. The message also dropped
the service's refusal and doubled the stateReason's period.

- The message now says the VM can't be resumed, that the service refused
  ResumeMicrovm, and the state and stateReason GetMicrovm reports, in
  parentheses so a stateReason's own period isn't doubled. It names no
  cause and says to launch a new VM.
- The refusal is attached as the error's source.
- WindowClosed now means the VM ended before the resume (the suspended
  window, the maximum duration, or a terminate), and it can't be resumed:
  in the ErrorKind doc, the exit table's meaning, the CLI hint (which no
  longer names --suspended-sec), the resume help, WindowClosedError and
  both bindings' ControlPlane.resume docs. docs/manifest.json,
  microvms.pyi and index.d.ts are regenerated. The code and exit 8 stay.
- A new test covers a VM a terminate ended: the exact neutral message, no
  doubled period, and the refusal as the source. The seeded fault
  resume-window-closed-drops-the-refusal removes the source and the test
  fails.
- The fail-to-pass patches are regenerated against the merge base, since
  they reverse every product hunk.
…uspended

The Sandbox.resume docs in both bindings, the core Sandbox docs and the
client model said a resume of a VM that terminated while suspended gets
WindowClosed, which reads as covering a VM the idle policy suspended.
Nothing updates a Sandbox's lifecycle when the platform idle-suspends its
VM: the sandbox still holds it as RUNNING, so Sandbox::resume refuses
with InvalidArg before any call (STATE-7) and never asks the service.
That refusal is unchanged here.

- The docs now say a sandbox doesn't see an idle suspend, that the
  suspend reaches a caller only through Sandbox::adopt, which reads the
  state from the service, or ControlPlane::resume, which holds no
  lifecycle, and that WindowClosed is the service's answer once a resume
  reaches it, whatever ended the VM. That's in Sandbox::resume and the
  module docs in crates/microvms-app, both bindings' Sandbox.resume with
  microvms.pyi and index.d.ts regenerated, the control-plane test's doc,
  and the client model's module docs, whose SuspendedVmEnded is the
  platform ending a VM the client suspended.
- The drop warning said "The VM bills until its maximumDurationInSeconds
  ceiling" about the lifecycle the sandbox last saw, which tells the owner
  of a VM the platform already ended that it still bills. It now names
  the state as the last one the sandbox saw, says the platform may have
  suspended or ended the VM since, and says a VM that's still live bills
  until it ends. The drop test asserts that wording.
- docs/insights/debugging-guide.md's sandbox.rs citation follows the
  lines, and the fail-to-pass patches are regenerated.
clock.rs's module docs still said Sandbox times the suspended window on
the plane's clock, and that a monotonic clock matters because a wall
clock stepping backward would reopen a closed window. #597 removed that
window check, so the docs now say what the clock serves: Sandbox waits
on the plane's clock so a deadline isn't measured on one clock while the
polls sleep on another, and Clock::elapsed is monotonic because a wait's
deadline and a proxy token's age are durations. The fail-to-pass patches
are regenerated, since they reverse every product hunk.
…mised; a Sandbox doesn't see an idle suspend

The 2026-10-12 re-measure held the idle policy fixed: two VMs suspended with
SuspendMicrovm under the idle case's own policy resumed about 910 s into a
60 s window. AWS documents the window for any suspended VM, so the resume and
--suspended-sec help, the CLI reference, the changelog and two site pages say
the explicit case is measured behavior AWS doesn't promise. The client no
longer depends on either answer: every resume goes to the service.

recover-a-leaked-vm.md and long-lived-vm.md now say ERR_WINDOW_CLOSED for an
idle-suspended VM comes from `microvm resume` and ControlPlane.resume, and that
a Sandbox that launched the VM refuses its own resume first (#603).
docs/behavior/processes.md no longer describes the suspend stamp and window
check this change removed, and its line references point at the current code.
…base

The six FAIL_TO_PASS patches reverse every product hunk of this fix, so the help-text change and the rebase onto main (f410ec2, #598 squashed) left them unable to apply. fail-to-pass.py's fix_patch regenerated them against the new merge base.
@laithalsaadoon
laithalsaadoon force-pushed the fix/resume-explicit-suspend-window branch from 3330dc6 to 4384885 Compare October 12, 2026 21:57
@laithalsaadoon
laithalsaadoon changed the base branch from docs/one-current-fact to main October 12, 2026 21:58
@laithalsaadoon
laithalsaadoon marked this pull request as ready for review October 12, 2026 22:21
Copilot AI balanced review requested due to automatic review settings October 12, 2026 22:21
@laithalsaadoon
laithalsaadoon merged commit a4047ea into main Oct 12, 2026
38 of 67 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

bonk-ai Bot added a commit that referenced this pull request Oct 13, 2026
tech-debt.md loses items 5 (napi generator pin, fixed by #576) and 10
(lifecycle commentary, fixed by #579) and the bullets that cited them;
item 8 now names #576's agreement test and the proof-runner copy it
leaves out. debugging-guide.md drops the Serve-not-Future entry that
#583's accept loop retired. 15 citations #600 and #601 moved on those
pages are re-pointed by exact text match. The see-also footers on 19
pages drop their hand-written citation counts (AGENTS.md, Counts in
docs), and .vale/warnings.json lowers 25 ceilings to this tree's counts.

docs:check EXIT=0 (240 s), prose:check EXIT=0 (0 errors, 4069 warnings).
bonk-ai Bot added a commit that referenced this pull request Oct 13, 2026
…607)

tech-debt.md loses items 5 (napi generator pin, fixed by #576) and 10
(lifecycle commentary, fixed by #579) and the bullets that cited them;
item 8 now names #576's agreement test and the proof-runner copy it
leaves out. debugging-guide.md drops the Serve-not-Future entry that
#583's accept loop retired. 15 citations #600 and #601 moved on those
pages are re-pointed by exact text match. The see-also footers on 19
pages drop their hand-written citation counts (AGENTS.md, Counts in
docs), and .vale/warnings.json lowers 25 ceilings to this tree's counts.

docs:check EXIT=0 (240 s), prose:check EXIT=0 (0 errors, 4069 warnings).

Co-authored-by: bonk-ai[bot] <269762587+bonk-ai[bot]@users.noreply.github.com>
bonk-ai Bot added a commit that referenced this pull request Oct 14, 2026
604 path:line citations on 15 hand-written pages pointed a few lines off after
#600 and #601 moved their source lines. Each move is the doc line's blame-commit
block found at HEAD by exact text and by git's own diff line mapping, or a
read-only audit against the sentence for the 20 rows neither settled.

state-machines.md's VmState section now says what ResumeRequested does after
SuspendedVmEnded (client.rs:494-499, 509-512): the service refuses the request
and the model writes Terminated.
bonk-ai Bot added a commit that referenced this pull request Oct 14, 2026
604 path:line citations on 15 hand-written pages pointed a few lines off after
#600 and #601 moved their source lines. Each move is the doc line's blame-commit
block found at HEAD by exact text and by git's own diff line mapping, or a
read-only audit against the sentence for the 20 rows neither settled.

state-machines.md's VmState section now says what ResumeRequested does after
SuspendedVmEnded (client.rs:494-499, 509-512): the service refuses the request
and the model writes Terminated.

Co-authored-by: bonk-ai[bot] <269762587+bonk-ai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

core: resume refuses an explicitly suspended VM past suspendedDurationSeconds, which the service still resumes

2 participants