Repository navigation
Bind masks to their fingerprints for the whole run and the relationship scan - #180
Conversation
Each mask's header is now read between two fingerprints that must agree (find_masks(bind=True), MaskFile.bound; else mask_changed_during_check), the manifest records that fingerprint instead of one taken when it is written, and every mask must still have it right before the commit (mask_changed_during_run, naming the mask and what changed; nothing is published). A verify_content run also hashes every mask after the header checks and again as the last step before the commit. No schema change: unchanged reruns keep the manifest byte for byte. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbytvF3Gsa85ix8Ne2yMDW
The mask step now fingerprints each mask with its header (prepare_mask_step binds the headers) and each image's masks before their first plane is read and after their last. A mask that no longer has the fingerprint taken with its header, went missing, or changed during its scan raises MaskChangedError (a ValueError; the error mask_changed_during_scan, which the masks command prints): no report is written and an earlier one is left as it was. With verify_content (prepare_mask_step(verify_content=...), masks --verify-content; by default the recorded run's setting) the content SHA-256 is compared too. The report format is unchanged and unchanged masks give the same report. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbytvF3Gsa85ix8Ne2yMDW
c07d452 to
6a0d62b
Compare
… it (#165) describe_masks raises MaskChangedError (a ValueError) when a mask changes while it is read. The notebook's Describe the masks caught it as an unusable mask and told the user to correct or replace the mask. It now shows the error card of mask_changed_during_scan, which names the mask and says to wait until nothing writes to it, as the masks command does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbytvF3Gsa85ix8Ne2yMDW
Independent review: approve after one fix (now at
|
Fixes #160, fixes #165
Summary
masks/checks.py,masks/files.py,run/preflight.py,mask_record.py,run/pipeline.py, newmask_binding.py: every mask's header is read between two fingerprints that must agree (find_masks(bind=True),MaskFile.bound). If they differ, the run stops with the new errormask_changed_during_check. The manifest now records that header-bound fingerprint; before, it was taken when the manifest was written. Every mask must still have the fingerprint right before the commit. Otherwise the run stops withmask_changed_during_run, which names the mask and what changed, and nothing is published. Averify_contentrun also hashes every mask after the header checks and again as the last step before the commit.mask_scan.py,run/mask_step.py,cli_masks.py:prepare_mask_stepbinds the mask headers.scan_masksfingerprints each image's masks before their first plane is read and after their last. Withverify_contentit also takes their SHA-256 (set throughprepare_mask_step(verify_content=...)ormasks --verify-content/--no-verify-content; by default the recorded run's setting). A changed or missing mask raisesMaskChangedError, aValueErrorsubclass (codemask_changed_during_scan). No report is written and an earliermask_relationships.jsonstays as it was. The report is still written whole by one rename after every image is scanned, so nothing half-written can look complete.Decisions
Notes for review
MaskChangedErrorthrough its existingValueErrorcard.notebook_mask_step.pyis untouched.RunInputsstill checks mask fingerprints only; it does not check mask content.Tests
tests/test_mask_run_binding.py(7) andtests/test_mask_scan_binding.py(10), covering TIFF masks and OME-Zarr label images. Against main's source, 15 of them fail. The other 2 are invariants that pass on main as well: an unchanged rerun keeps the outputs byte for byte, and the default run's stated blind spot.python tools/check.py(Linux, Python 3,.[dev,notebook,zarr]): ruff check and format clean; 2311 passed, 4 skipped (3 need a case-insensitive file system, 1 needs permissions that root ignores); code rules clean.🤖 Generated with Claude Code
https://claude.ai/code/session_01VbytvF3Gsa85ix8Ne2yMDW