Repository navigation
Stage a Modal run's copied-back outputs through the re-stage command - #1499
Merged
Merged
Conversation
anth-volk
added a commit
that referenced
this pull request
Nov 3, 2026
Review round 1 of #1499. New and changed tests describe what the command does not do yet, each failing on an assertion: - an edited build manifest (a field, another file the stage wrote registered as an output, a renamed role) is refused while its staged_dataset record is still the build's own; - the receipt's status and the run directory's place are checked before any output is hashed; - an output the stage hashed but never copied to the runs volume (outputs_not_mirrored) gets its own message; - the default state root is resolved, so a state directory that is a symbolic link still describes the copied-back files; - a malformed build manifest is an error message, not a traceback. Other new cases pass already and guard the same checks: an output whose receipt entry has other bytes, a run directory named through a link or through .., a link in the state directory that leads outside it, and a --local-only run that leaves the build manifest's bytes unchanged. The installed-emitter test now takes the run id from the build's local_only record instead of --run-id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Nov 3, 2026
Review round 1 of #1499. - The build manifest must have the receipt's SHA-256 and size while its staged_dataset record is still the build's own (anything but a local_and_remote record), so an edited manifest cannot register another file the stage wrote, rename a role or change other fields. A --local-only re-stage writes the same record in the build's own JSON rendering, so the bytes stay the receipt's; after a hand-over the manifest is not compared, so a second run on a landed bundle works. - The receipt's status, the run directory's place under the state directory, and the receipt's listing of the manifest and of every registered output are checked before any output is hashed. An output in the receipt's outputs_not_mirrored that the copy-back lacks gets its own message. The default state root is resolved, as --modal-state-root is. - A build manifest that is not valid JSON or not a JSON object is an error message rather than a traceback. - Docs: a UK build on Modal is described as a possible future case, the US release manifest's artifacts is a mapping, and --local-only also rewrites the build manifest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A UK build run on Modal records its bundle as local_only, because the runner sets HF_HUB_OFFLINE. These tests describe the workstation side: after modal volume get, the re-stage command takes the stage's receipt (--modal-receipt), checks every output the manifest registers against it, and hands the bundle to the operator's emitter with the re-stage code. They cover the hand-over and its records, refusals of a directory whose outputs do not match the receipt or the manifest, a receipt of an unfinished stage, a directory outside the run's state, a second run on a landed bundle, a retry after a failed first attempt, and HF_HUB_OFFLINE left set on the workstation. The fake Hub, the re-stage emitter and the output-editing helpers move to test_support so both UK test modules share them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A UK build run on Modal records its bundle as local_only, because the runner sets HF_HUB_OFFLINE for every tool. After modal volume get, --modal-receipt names the stage's receipt: the command refuses a receipt of a stage that did not finish, a directory outside the run's copied-back state directory, and any registered output whose SHA-256 or size differs from the receipt's, before it starts an emitter. A directory that matches is staged by the existing re-stage code, so its records, retries and landed-bundle handling are a local directory's. The manifest and sidecars are not compared, because staging rewrites them. An output that does not match its manifest digest is now an error message rather than a traceback. One installed-emitter test runs the command against the stand-in Hub. The UK staging guide and the Modal runbook describe the command; the runbook also says why no US program writes a staged bundle yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 1 of #1499. New and changed tests describe what the command does not do yet, each failing on an assertion: - an edited build manifest (a field, another file the stage wrote registered as an output, a renamed role) is refused while its staged_dataset record is still the build's own; - the receipt's status and the run directory's place are checked before any output is hashed; - an output the stage hashed but never copied to the runs volume (outputs_not_mirrored) gets its own message; - the default state root is resolved, so a state directory that is a symbolic link still describes the copied-back files; - a malformed build manifest is an error message, not a traceback. Other new cases pass already and guard the same checks: an output whose receipt entry has other bytes, a run directory named through a link or through .., a link in the state directory that leads outside it, and a --local-only run that leaves the build manifest's bytes unchanged. The installed-emitter test now takes the run id from the build's local_only record instead of --run-id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 1 of #1499. - The build manifest must have the receipt's SHA-256 and size while its staged_dataset record is still the build's own (anything but a local_and_remote record), so an edited manifest cannot register another file the stage wrote, rename a role or change other fields. A --local-only re-stage writes the same record in the build's own JSON rendering, so the bytes stay the receipt's; after a hand-over the manifest is not compared, so a second run on a landed bundle works. - The receipt's status, the run directory's place under the state directory, and the receipt's listing of the manifest and of every registered output are checked before any output is hashed. An output in the receipt's outputs_not_mirrored that the copy-back lacks gets its own message. The default state root is resolved, as --modal-state-root is. - A build manifest that is not valid JSON or not a JSON object is an error message rather than a traceback. - Docs: a UK build on Modal is described as a possible future case, the US release manifest's artifacts is a mapping, and --local-only also rewrites the build manifest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
force-pushed
the
modal-outputs-staging
branch
from
November 4, 2026 08:34
3790efa to
0450f5d
Compare
… (failing) Review round 2 of #1499 found two gaps in the copied-back staging tests. - A --local-only run with --modal-receipt writes a new local_only record into the build manifest. When that record differs from the build's own, every later run with the receipt refuses the unedited directory. The new parametrized test covers the build's own local_only record, a build that disabled its staged dataset, another --run-id and a run after a failed hand-over. A new national test covers a build that rewrites its build record after it records its staged dataset. The case where the build wrote its own local_only record passes already; the other four fail on the manifest-bytes assertion. - No test reached the comparison of each output with its receipt entry through an edited output, because _edit_an_output also changes the build manifest and the manifest comparison refused it first. The refusal case now edits an output under a record edited to say it was handed over, where the manifest is not compared. A new test edits an output after a real failed hand-over. Both pass already; they pin which edits the checks catch once the manifest is no longer compared. - The landed-bundle test also runs --local-only with the receipt, and a new test checks that --local-only without the receipt still records the bundle in the build manifest. Both pass already. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A --local-only run wrote a new local_only record into the build manifest. That record differs from the build's own when the build disabled its staged dataset, when --run-id names another run id, when a national build changed its outputs after recording its staged dataset, and after a hand-over. The manifest then still counted as the build's, so it was compared with the receipt, but no longer had the receipt's bytes, and every later run with --modal-receipt refused the unedited directory. With --modal-receipt, --local-only now checks the directory, writes staged_manifest.json and sha256sums.txt, prints the local_only record and leaves the build manifest as it is. Without --modal-receipt it records the bundle in the build manifest as before. The manifest comparison reads staged_dataset.mode from the manifest itself, so a manifest edited to say local_and_remote is not compared either; the outputs still are. No condition read from the manifest can tell such an edit from a record a hand-over wrote. The command's docstring and help text, the UK staging guide, the Modal runbook's pointer and the changelog fragment now say which edits the checks catch and which they do not, and the --local-only help text says what it writes in each case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A hand-over from the workstation writes its local_and_remote record into the build manifest only when the emitter copied the manifest; a manifest the emitter uploads from disk stays as handed over, keeps the receipt's bytes and is still compared. The command's docstrings, the UK staging guide and the changelog fragment now say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…11-04 incident Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 3 of #1499 (code-quality point 4): no test covered a hand-over whose emitter queues the bundle without copying the build manifest. The command then leaves the manifest as handed over, with the receipt's bytes and the build's local_only record, so the next run with the receipt still compares it. The new test edits the manifest after such a hand-over and checks that the next run refuses it before an emitter starts. It guards existing behaviour, so it passes before and after the documentation changes that follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 3 of #1499 (code-quality points 1 and 2): - The --modal-receipt help and the Modal runbook's pointer now say that the build manifest's record is read from the manifest itself, so an edit that says a hand-over happened is not caught. - "Later runs with the receipt still compare it" now holds only for a manifest that still has the build's record. - Any attempt that records its outcome in the manifest writes a local_and_remote record, refused attempts included; a bundle queued without a copy of the manifest leaves the manifest as handed over. - The module docstring is wrapped again, and its refusal sentence no longer reads as the reverse of the one before it. - The changelog fragment describes the hand-over before --local-only. - The UK staging guide and the --local-only help warn that --local-only without --modal-receipt writes a local_only record, which on a copied-back directory can make every later run with the receipt refuse it, and say to pass the receipt. - The note --local-only prints with the receipt no longer says later runs compare the manifest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1498
What this changes
No UK program is registered with the Modal runner yet. A UK build run there would record its bundle as
local_only: the runner setsHF_HUB_OFFLINE=1for every tool, so the build would hand its emitter nothing (#1460). This adds the workstation side for that case. Aftermodal volume gethas copied such a run back:microcosm-modal-us-stage-receipt/1receipt, a receipt of a stage that did not finish (receipt_status_problems: notCOMPLETED, orstopped_at_budget), and a run directory whose real location (after links and..) is outside the copied-back state directory. That directory isstate/besidereceipts/, or--modal-state-root, and both are resolved the same way. The receipt must also list the build manifest and every output it registers. An output in the receipt'soutputs_not_mirroredthat the copy-back lacks is named as such.local_and_remote. Unless the build manifest'sstaged_datasetrecord has the modelocal_and_remote, the manifest must have the receipt's SHA-256 and size. So a manifest edited to register another file the stage wrote, rename a role or change any other field is refused. An attempt to hand the directory over from the workstation that records its outcome in the manifest writes alocal_and_remoterecord, whether the bundle landed, failed or was refused, so after such an attempt the manifest is not compared, and a second run on a landed bundle still works. A bundle the emitter queued without copying the manifest leaves the manifest as handed over, with the receipt's bytes and the build's record, and it is then still compared.local_and_remote. Such an edit also turns the manifest's comparison off, and the edits above are then not caught. No condition read from the manifest can close this; see "Review round 2" below.staged_manifest.jsonandsha256sums.txtare not compared, because staging writes them again.stage_bundle, thestaged_dataset,staged_dataset_handoverandstaged_dataset_at_buildrecords, the rule that a landed record is never replaced, and the note about the build's other records. The staged run id is the build's own, from itslocal_onlyrecord.HF_HUB_OFFLINEon the workstation is refused as for any re-stage, before an emitter starts.--local-onlywith--modal-receiptchecks the directory against the receipt and writesstaged_manifest.jsonandsha256sums.txt, but leaves the build manifest as it is, so a manifest that still holds the build's record is still compared by later runs with the receipt. It prints thelocal_onlyrecord the manifest does not get. A directory whose manifest records a landed bundle is left unchanged.--local-onlywithout--modal-receiptstill records the bundle aslocal_onlyin the build manifest, as before. On a copied-back directory that record can make every later run with the receipt refuse the directory, so the guide and the--local-onlyhelp warn against it and say to pass the receipt; if it has happened, fetch the run again withmodal volume get.error: ..., with or without--modal-receipt.tools/modal_us_stage_plan.py(standard library only), imported the waytools/modal_us_stage.pyimports it.Review round 2
--local-onlycould leave a directory that every later run with the receipt refused. It wrote a newlocal_onlyrecord into the build manifest. That record differs from the build's own when the build disabled its staged dataset (--no-staged-datasetor--no-staging), when--run-idnames another run id, when a national build changed its outputs after recording its staged dataset (it rewrites its build record, and registers its score receipt when it has one), and after a hand-over. The manifest then still counted as the build's but no longer had the receipt's bytes. With--modal-receipt,--local-onlynow leaves the build manifest as it is (_leave_the_copied_back_manifest).staged_dataset.modeturns the manifest's comparison off. The claims are narrowed: the description, the guide, the command's docstring and help text, the runbook's pointer and the changelog fragment now say the comparison applies unless the record islocal_and_remote, and that an edit setting that mode is not caught, while the outputs still are.validate_staged_dataset_deliveryaccepts as remote or astaged_dataset_handoverblock, can be written by the same edit, so it would let the manifest vouch for itself. A sound check would rebuild the manifest the stage wrote and compare its hash with the receipt's. That works only with the build's originalstaged_datasetrecord, and after a hand-over the manifest does not keep it:staged_dataset_at_buildholds only the mode, status and error code. The record cannot be recomputed from the outputs either: adisabledrecord's opt-out reason is gone, another--run-idchanges it, and a national build's record predates its rewritten build record. A rebuild from what is left would refuse legitimate second runs in those cases, or would have to skip the check, which an edit could then choose. Storing the build's record in the manifest at the first hand-over would make the check sound, because the rebuilt bytes must hash to the receipt's digest, so only the records the command writes could differ. It adds a key to the build manifest that is uploaded with the bundle, which is a decision for later, once a UK program is registered with the Modal runner.Review round 3
No bugs. Documentation edits for its code-quality points 1 and 2, and a test for point 4:
--modal-receipthelp and the Modal runbook's pointer now also say that the record is read from the manifest itself, so an edit that says a hand-over happened is not caught. Round 2's statement above about those two texts is now true.local_and_remoterecord, refused attempts included. Before, the texts said only "when the emitter copied the manifest".--local-only, which hands nothing over.--local-onlywithout the receipt on a copied-back directory, above.test_a_build_manifest_the_emitter_did_not_copy_is_still_compared: a hand-over whose emitter queues the bundle without copying the build manifest (never_copy) leaves the manifest as handed over, and the next run with the receipt refuses an edit made after it. It guards existing behaviour.Round 3's other points wait until a UK program is registered with the Modal runner: the stricter check it describes (comparing the build manifest with the receipt just before a new hand-over, whatever its record says), and the
HF_HUB_OFFLINErefusal that still comes after every output is hashed.What this does not do
start_bundle_emitter()), and no build submits artifacts to the collector's artifact intake yet (Accept artifact submissions into private storage and run worker jobs microcosm-collector#12). That part waits on turning the intake on and then on builds submitting to it. Telemetry goes to the collector from wherever the build runs; for a Modal build, the container sends it.packagestage's release directory has its ownrelease_manifest.json(anartifactsmapping, notoutputs) and its ownsha256sums.txt, the file name the bundle's checksum file uses. Staging a US build's datasets needs a private repository, a manifest that registers the outputs, and a command that reads it.Tests
packages/microcosm-build/tests/engine_free/uk/test_uk_modal_copy_back_staging.py(32 cases): a synthetic dense build run withHF_HUB_OFFLINE=1, moved into a copied-back Modal layout with a receipt (test_support/microcosm_build/modal_copy_back.py). It covers:stage_bundle;--modal-state-root, astatedirectory that is a symbolic link, a run directory named through a link or through.., and a link in the state directory that leads outside it;--local-only; a retry after a first attempt without a credential, which records the queued hand-over asalready_staged;--local-onlywith the receipt leaving the build manifest for a later staging run: with the build's ownlocal_onlyrecord, a build that disabled its staged dataset, another--run-id, and after a failed hand-over;--local-onlywithout the receipt still recording the bundle in the build manifest;HF_HUB_OFFLINEleft set on the workstation; a malformed build manifest.test_a_local_only_check_of_a_copied_back_national_build_leaves_its_manifestintest_uk_rowwise_national_role.py: the same--local-onlycheck on a national build run withHF_HUB_OFFLINE=1.test_a_modal_runs_copied_back_outputs_are_staged_by_the_re_stage_commandin the installed-emitter tests runs the command against the installed emitter and the stand-in Hub, taking the run id from the build'slocal_onlyrecord._remote_hub,_bundle_emitter_forand_edit_an_outputmove fromtest_uk_full_build_cli.pytotest_support/microcosm_build/uk_full_build_cli.py, which both UK modules import. They serve 11 test cases there.Run locally
Each by node ID from an explicit list that refuses to run when empty, with
HF_HUB_OFFLINE=1, Python 3.13 anduv sync --all-packages --locked. CI runs everything else.Round 2's tests at
a5ea5db76(failing tests, before the fix): 4 failed and 5 passed. Each failure is anAssertionErroron the assertion that the build manifest's bytes are unchanged after--local-onlywith the receipt:test_a_local_only_check_with_the_receipt_leaves_the_build_manifest[a build that disabled its staged dataset],[another --run-id]and[after a failed hand-over];test_a_local_only_check_of_a_copied_back_national_build_leaves_its_manifest.The 5 that passed guard behaviour the fix keeps:
[the build's own local_only record],test_a_local_only_run_without_the_receipt_records_the_bundle_as_before,test_a_copied_back_bundle_that_landed_is_not_handed_over_again(now also with--local-only),test_an_output_edited_after_a_failed_hand_over_is_refused_by_its_receipt_entry, andtest_a_copied_back_directory_that_does_not_verify_is_refused[an output edited under a record edited to say it was handed over]. The last two pin the narrowed claim, which needed no code change.The same 9 at
9e508a4fc(the fix), at2af2d1c0f(after mergingmain, which brought Stop a build that must send telemetry when its emitter cannot start #1465) and at6adad928f(wording only): all passed.Round 3, at
dce6e1e5d(after mergingmainagain at0f0e777b2, which brought Calibrate the QRF sign gates out of fold, for every gated UK imputation #1391 and Give a stage launched on Modal a telemetry-only collector token #1473): the 9 andtest_a_build_manifest_the_emitter_did_not_copy_is_still_compared, 10 passed.test_a_modal_runs_copied_back_outputs_are_staged_by_the_re_stage_command, with--run-integration, with microcosm-emitter 0.11.9 and 0.12.0 each installed into its own folder with the runner script'suv tool installcommand and constraints file: passed with both.In review round 1, 11 of the first 26 cases failed on an assertion before the change.
ruff checkandruff format --checkon the changed Python files, andtools/ci_test_plan.py verify.Environment variables
No variable is added, and no workflow, Docker, Terraform or Modal configuration changes.
HF_TOKEN, thenHUGGINGFACE_TOKEN, then the tokenhf auth loginsavedHF_TOKENtheinstalled_emitterfixture sets, which also removesHUGGINGFACE_TOKENandHUGGING_FACE_HUB_TOKEN; never a credential.HF_HUB_OFFLINE,TRANSFORMERS_OFFLINEhub_offline()in the commandtool_environmentsetsHF_HUB_OFFLINE=1POPULACE_UK_STAGED_DATASET_REPO_ID--repo-iddefaultuk_runtime/staging.py)MICROCOSM_EMITTER_COMMANDPATH); in CI,tools/run_installed_emitter_tests.shINSTALLED_EMITTER_VERSIONinstalled_emitterfixturetools/run_installed_emitter_tests.shXDG_CACHE_HOME~/.cache); a temporary directory in the testsHF_ENDPOINT,HF_HUB_DISABLE_XET,HF_HUB_DISABLE_TELEMETRY,HF_HOME, proxy variableshuggingface_hub, in the installed-emitter test onlyinstalled_emitterfixturemonkeypatchand inherited by the emitter process.MICROCOSM_TELEMETRY_REQUIRED, which #1465 added, is read only when a build starts its telemetry emitter;start_bundle_emitter(), which this command uses, does not read it. TheMICROCOSM_MODAL_TELEMETRY_*variables #1473 added are read inside the Modal runner's own functions intools/modal_us_stage_plan.py; the command imports that module only forRECEIPT_SCHEMAandreceipt_status_problems, so it does not read them.🤖 Generated with Claude Code