Repository navigation
PP-10d: the notebook's masks-step button (Describe the masks) - #123
Merged
Merged
Conversation
…nly) The pairing with the recorded inputs, the scan and the write of mask_relationships.json under the output folder's lock move from cli_masks.masks_command into run.mask_step (orchestration): prepare_mask_step returns a MaskStep (preflight, output folder, input changes, blocking issues, or the experiment_not_recorded refusal) and describe_masks scans and writes, returning the output_locked refusal instead of raising. The CLI only prints their results; its output is unchanged (same text and exit codes over 13 scenarios, HPMEC included). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
After a run that recorded masks, step 3's "Describe the masks (optional)" card runs the masks step with the run's recorded inputs through run.mask_step (the functions the CLI calls), with a progress bar, and shows the mask types, relationships with their counts, masks of the same objects and the hierarchy as suggestions to check, with the path of mask_relationships.json. Refusals use the existing cards (lock card with the stale-lock button; red cards for mask errors and unusable masks). Default thresholds only, said on the card. Hidden with folder_step(show_output=False); embedding API unchanged (private handler). run.mask_step.recorded_mask_types gates the button. The masks' texts move from report.py to mask_text.py (pure) with the new table rows, keeping report.py within 600 lines. Docs: notebook, user guide, contract §9.2/§15.1, plan §10, AGENTS.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Checked on the HPMEC data rendered in a browser: the headings sat on the table above them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
guijacquemet
marked this pull request as ready for review
November 2, 2026 12:45
Coordinator decision 1: describe_masks takes the lock before the first mask is read and holds it to the write of mask_relationships.json, so the command line's masks and the notebook's Describe the masks refuse a locked output folder (output_locked) before reading any mask. MaskStepResult's report is None on that refusal. Regression tests: the refusal reads no mask, the lock is held during every progress call, and the command prints no progress line when locked. Docs: contract §9.2 and §15.1, user guide, plan §10, the CLI module's notes; the notebook's lock card says no mask was read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
…ned notebook Coordinator decision 2: the button is enabled when step 1's output folder holds a v2 manifest that recorded masks, not only after a run in this session. run.mask_step.recorded_masks (replacing recorded_mask_types) returns a RecordedMasks (output folder, experiment folder, masks folder, mask types, when written); the help line names the run it describes, and a click runs prepare_mask_step(None, output_folder), the path the CLI's masks --output takes. The card follows step 1's output folder (re-read when the manifest's fingerprint changes), is never offered with show_output=False (folder_step refreshes it), and a moved experiment or masks folder is refused with the existing messages under a title that no longer says the masks have errors. Regression tests: reopened notebook (report equal to the CLI's), output folder edits, moved experiment and masks folders, no run, embedding brick. Docs: contract §9.2, user guide, plan §10, AGENTS.md, notebook. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
mask_text._hierarchy_lines kept its # noqa: ANN001 through the move; §9 asks moved functions to be annotated. The ANN noqa ratchet shrinks 55 -> 54. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Contributor
Author
|
Independent review, then merged as merge commit 5044992 (main was 94fd6ac). Findings and fixes (on the PR branch)
Verified
§9 figures (touched files)
The PR branch was auto-deleted on merge and has been restored at Generated by Claude Code |
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.
PP-10d (owner decision of 2 November 2026: right after PP-10c, before PP-11). Design v0.4 §1 (recorded inputs, lock), §2 (masks), §9 code standards; contract §15 (the mask step). Plan §10 PP-10d.
Summary (by module)
run/mask_step.py(new,orchestration). Commit2f1bf1fis a move only: the pairing with the recorded inputs, the scan and the write under the lock leavecli_masks.masks_command.prepare_mask_step(experiment_root, output_folder, *, exclude=, masks_folder=, mask_axes=)returns aMaskStep: the preflight, the output folder, the input changes with their effect and the blocking issues, or theexperiment_not_recordedrefusal.MaskStep.readyis true when nothing is refused, there are no errors and at least one mask type exists.describe_masks(step, *, thresholds=, progress=)returns aMaskStepResult(the report and the path written). Review (coordinator decision 1): the output folder's lock is taken before the first mask is read and held until the write. A locked folder returns theoutput_lockedrefusal (report=None) before any mask is read. It raisesValueErrorfor masks whose pixels cannot be used, as before.recorded_masks(output_folder)replacesrecorded_mask_types. It returns aRecordedMasks(output folder, experiment folder, masks folder, mask types,written_at) from a v2 manifest, or None without one.morphobricks_preprocessing.run.cli_masks.py: only parses and prints. Its output is unchanged except in one case: a locked output folder is now refused before any progress line.notebook_mask_step.py(new,ui): step 3's Describe the masks (optional) card, placed after the intensity checks.prepare_mask_step(None, output_folder), the same path as the CLI'smasks --output. If the experiment or masks folder has moved, the step is refused with the existing messages.mask_text.mask_text.py(new,pure):mask_summary,mask_report_summaryand their helpers, moved unchanged fromreport.py. The review added an annotation to_hierarchy_lines, which removes its# noqa: ANN001. New here:mask_type_rows,mask_relationship_rows,mask_hierarchy_linesandmask_thresholds_used.notebook_ui.py/notebook_run.py: the mixin and the card.folder_step(show_output=False)hides the card and never offers the step._start_runclears and disables it while a run runs.masks, §6 lock), contract §9.2 (themasksand Lock rows, and the Notebook mask step row) and §15.1 (the lock), plan §10, and AGENTS.md.Behaviour changes
masks: with a locked output folder, the command is refused before any mask is read: no[i/n]progress lines, the sameoutput_lockedmessage and exit 1. Every other scenario is byte-identical to main.run.MaskStep,MaskStepResult,RecordedMasks,prepare_mask_step,describe_masksandrecorded_masks.report.mask_summaryandreport.mask_report_summarymoved tomask_text(they were not top-level API).tests/test_embedding_api.pyis untouched and passes.Evidence
2f1bf1f): the reviewer reran the comparison independently. 23 CLI scenarios (stdout, exit status andmask_relationships.jsonwithoutversions) ran onmain94fd6ac and on2f1bf1f.MorphoRelate/data/hpmec_perfusion) in a reopened notebook: a freshPreprocessingNotebookon an output folder written earlier by the CLIrun.mask_relationships.jsonequals the CLI's.Tests
3f3b206: own worktree and uv venv, Python 3.11,.[dev,notebook,zarr].ruff checkandruff format --checkare clean, andtools/check.py --rulespasses.tests/test_discovery.py:665, file modes ignored when running as root.tests/test_mask_step.py(10) andtests/test_notebook_mask_step.py(14).run.mask_stepis missing.§9 figures (final head)
notebook_mask_step.py280 lines,run/mask_step.py259,mask_text.py177,cli_masks.py109,report.py436. The largest file touched isnotebook_ui.pyat 480._build_mask_step_card(38 lines).masks_command(44).masks_command).prepare_mask_step); 6 in the touchedfolder_step, which is unchanged.masks_command).run.mask_stepis orchestration,mask_textpure, andnotebook_mask_stepui.# noqacount went 55 → 54 and the baseline was lowered. There is no new exemption.Colab hand-check list
mask_relationships.jsonappears in the output folder.🤖 Generated with Claude Code
https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc