Skip to content

feat(sandbox): let a configured sizer choose the sizes deploy steps leave unset - #497

Open
kaihackney-scale wants to merge 7 commits into
mainfrom
kai/fd-5242-5241-default-sizing
Open

kaihackney-scale wants to merge 7 commits into
mainfrom
kai/fd-5242-5241-default-sizing

Conversation

@kaihackney-scale

@kaihackney-scale kaihackney-scale commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Lets a deployment choose the default cpu and memory of sandboxes while every size a step sets still wins.

  • [sandbox.sizer], a new impl / config table under [sandbox] (the same shape as [runner]), names a SandboxSizer (providers/sandbox_providers/sizing.py). The in-tree default is the base class, which chooses nothing, so without the table nothing changes.

  • deploy_env, deploy_agent and deploy_sandbox resolve each of cpu and memory separately, in this order:

    1. the step's own value;
    2. else the sizer's;
    3. else the step's default (deploy_sandbox's 1 vCPU / 8 GiB), or, with none, the provider's.

    The sizer is asked only when the step leaves something unset.

  • Each sandbox's attribution gains cpu_source and memory_source (step, sizer or default), so a deployment can see how many sandboxes each source sizes. Providers carry attribution as they do today; on Modal these are two more sandbox tags.

  • deploy_sandbox keeps an unsized cpu and memory as None on the step and in its stored dict, instead of writing 1.0 and 8192. It still reserves 1 vCPU and 8 GiB, but a size the step chose can now be told apart from one it left to the default. Steps already stored keep the values they were written with.

Notes for review

  • Not an entry-point group. A sizer is one policy per deployment, like the runner, so it's a config seam with an in-tree default rather than a registry of named types.
  • No pinning across retries. The size is resolved when the step deploys, so a retried deploy asks the sizer again. A sizer whose answer can change mid-run is responsible for keeping one answer per run (attribution carries run_id).
  • A failing sizer fails the deploy, as a failing provider would. No caller produces a sizer that should be ignored.
  • A linked sandbox: deploy_agent into an existing sandbox still resolves a size (and its sources) though the sandbox already exists; the value is unused there, as cpu / memory_mb already were.

Tests

  • tst/unit/task_step/sandbox_sizer_test.py:
    • the precedence for each field and its source;
    • a step that sets both never asks the sizer;
    • an impl that isn't a SandboxSizer is refused;
    • deploy_env hands the sized values and sources to the env;
    • deploy_sandbox falls back to its own default when the sizer chooses nothing.
  • tst/unit/task_step/deploy_sandbox_default_cpu_test.py: an unsized step stays None through to_dict / from_dict and still reserves 1 vCPU and 8 GiB; stored sizes are kept; a memory-only step keeps the default cpu.
  • tst/unit/task_step/attribution_serialization_test.py: the dict deploy_env hands the env is the step's attribution plus the two source keys.
  • make lint is clean.
  • tst/unit plus the protocol tests, locally on macOS (-n 4): 12,992 passed, 6 failed before the attribution fix, 4 after.
    • The 4 left are test_disk_recipe.py's two launcher tests (QEMU/KVM) and test_mcp_cli_builder.py's two codegen tests (click missing from the generated venv). They fail the same way on an untouched main checkout on this machine.
    • tst/unit/artifact/test_docker_image_github_clone.py was left out locally. Its git credential fill waits on the macOS Keychain helper that Apple's Command Line Tools git configures outside GIT_CONFIG_NOSYSTEM. CI runs it.

Docs: the site's [sandbox] configuration page should list [sandbox.sizer] and the two attribution keys.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The final change appears safe to merge.

Summary

The final change keeps unset sizes separate from explicit sizes in DeploySandboxTaskStep, while preserving the resources it reserves.

  • Sandbox steps keep omitted sizes unset while still using the same defaults.

The latest commit deliberately removes the runtime sizer described in the PR text. The earlier saved-size finding is addressed; removing the sizer and generated size-source keys also removes the conditions behind the other two previous threads. Those threads were unnumbered, so they have no previousFindings entries.

Review checks were limited to code, tests, and commit history; tests were not run.

Reviews (6) · Last reviewed commit: "refactor(sandbox): drop the runtime size..." · Reviewed by Greptile

t and others added 2 commits November 4, 2026 15:42
A deploy_sandbox step that sets no cpu or memory still reserves 1 vCPU and
8 GiB, but now keeps both as None on the step and in its stored dict
instead of writing 1.0 and 8192. A size the step chose can then be told
apart from one it left to the default, which a default sizer needs.

Steps stored with explicit values keep them; nothing else reads these
fields.

FD-5242

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eave unset

[sandbox.sizer] names a SandboxSizer (impl/config, as [runner]). For each of
cpu and memory, deploy_env, deploy_agent and deploy_sandbox reserve the step's
own value, else the sizer's, else the step's or the provider's default. The
in-tree default sizer chooses nothing, so without the table nothing changes.

Each sandbox's attribution gains cpu_source and memory_source (step, sizer or
default), so a deployment can see which sizes it set.

FD-5241

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kaihackney-scale
kaihackney-scale requested a review from a team as a code owner November 4, 2026 22:29
t and others added 2 commits November 4, 2026 17:36
In container mode only the gateway gets the step's memory; its MCP servers,
sidecars and service db are created with cpu alone, so they get the
provider's memory. Their attribution said the step's memory source anyway.
They now carry memory_source "default".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t fail a deploy

- The sizer is passed vm=True when a step may deploy onto a VM: a vm-mode
  deploy_sandbox, or a deploy_env/deploy_agent whose sandbox type names a
  backend that creates VMs (may_create_vm, read from the classes).
- A sizer that raises or returns something other than a SandboxSize is logged
  and taken to choose nothing.
- A stored deploy_sandbox step with the old default pair (1.0, 8192), which
  every unsized step was saved with, reads as unsized; to_dict leaves an unset
  size out rather than writing null.
- A gateway's containers that don't take the step's memory get the source
  "provider", so their events aren't read as sized.
- cpu_source/memory_source stay out of the names, labels and tags boat,
  daytona, sail_vm, coreweave and tenki build from attribution.
- [sandbox] sizer = "pkg:Cls" works at runtime, as describe already accepted.

FD-5241, FD-5242

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
t and others added 3 commits November 9, 2026 13:17
…aved 1.0/8192

A container-mode deploy_sandbox on a VM backend (modal_vm) runs in a VM of its own whose
memory is the size chosen, so the sizer is now told vm=True for it too.

A step that sets cpu=1.0 and memory_mb=8192 is now saved with size_set, so a reload keeps
the pair instead of reading it as a step stored before sizes could be unset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A stored cpu=1.0 / memory_mb=8192 was read as unset when it carried no size_set marker,
so a step saved with that size before this change could be resized by a sizer. A stored
size is now always the step's own; only a field the dict leaves out is unset. The
size_set marker is no longer needed and is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sizes

Sizes now live on the task: measured usage suggests them and a person applies them as a
task edit, so nothing chooses a size while a run deploys. This removes the [sandbox.sizer]
seam (sizing.py, may_create_vm, the size-source attribution keys and the provider name
hygiene that went with them) and leaves deploy_env and deploy_agent as on main.

deploy_sandbox keeps the part that stands on its own: cpu and memory_mb may be unset (None),
an unset size is left out of the stored dict, a stored size is kept as written, and an unset
size reserves 1 vCPU / 8 GiB as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

3 participants