From 05d763a1a0af2436957b860579a2c0636d3929de Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 14 Nov 2026 15:35:56 +0000 Subject: [PATCH 1/2] Prepare v0.5.4: RGB header override and mask-only RGB requests - pyproject: version 0.5.4; normalization stays at @v0.6.0 (95e1d6d). - The notebook's current_version/RELEASE_TAG, the version index and the README pins: 0.5.4. RELEASE_REF stays at v0.5.3's 14f6b1a, as in the earlier commits A; the next commit points it at this one. - CHANGELOG: "v0.5.4 (14 November 2026)" with Added (the RH1 header override, #295), Changed (Spec re-pinned to b635b7d) and Fixed (mask-only requests on RGB units, #298, Spec section 8). No format version changes: the manifest's new unit keys are additive. - AGENTS.md status: v0.5.4. - docs/colab-release-check.md and tests/test_notebook_setup.py: preprocessing 0.5.4. - docs/conformance.md: the v0.5.4 release record (check.py 5600 passed, 4 environment skips; Spec modules 1839 passed, 0 skipped, 25 modules), measured on this tree before the record. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VbytvF3Gsa85ix8Ne2yMDW --- AGENTS.md | 7 ++++--- CHANGELOG.md | 17 +++++++++++++++- README.md | 8 ++++---- docs/colab-release-check.md | 4 ++-- docs/conformance.md | 23 ++++++++++++++++++++++ notebooks/MorphoBricks_Preprocessing.ipynb | 4 ++-- notebooks/notebook_latest_versions.yaml | 2 +- pyproject.toml | 2 +- tests/test_notebook_setup.py | 18 ++++++++--------- 9 files changed, 62 insertions(+), 23 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ced026a..45dae65 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1099,10 +1099,11 @@ jupyter lab notebooks/MorphoBricks_Preprocessing.ipynb --- -## 11. Status (current state, v0.5.3) +## 11. Status (current state, v0.5.4) -- **Released:** v0.5.3 (13 November 2026), with the normalization brick pinned at v0.6.0 (v0.5.2, - 12 November 2026, pinned it at v0.5.0). The +- **Released:** v0.5.4 (14 November 2026): the RGB header override (Spec RH1) and mask-only + requests on RGB units; the normalization brick stays pinned at v0.6.0 (since v0.5.3, + 13 November 2026; v0.5.2, 12 November 2026, pinned it at v0.5.0). The per-release history is in [CHANGELOG.md](CHANGELOG.md); the milestones PP-0 to PP-13 are in [docs/archive/plan-milestones-v0.1-v0.4.md](docs/archive/plan-milestones-v0.1-v0.4.md); the older status log of this file is in diff --git a/CHANGELOG.md b/CHANGELOG.md index 197f318..4c83ef8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,13 @@ The design is `docs/restart/preprocessing-design-v0.4.md` in MorphoFeature, on b are in [docs/plan.md](docs/plan.md) §12. (The v0.3 to v0.4 migration guide was removed in v0.5.1: no run before v0.5.1 is read.) -## Unreleased +## v0.5.4 (14 November 2026) + +RGB scanner input: the RGB header override of Spec amendment RH1, and mask-only requests on RGB +units (Fixed, below). The normalization pin stays at v0.6.0. Run manifest version 5, +`plane_histograms.csv` schema version 5, resolver contract version 2 and conversion record +version 4 are those of v0.5.3; the manifest's new unit keys are additive (only units declared +`rgb` carry them), and a v0.5.3 run is read as it is. The Spec pin moves to `b635b7d` (Changed). ### Added @@ -45,6 +51,15 @@ v0.5.1: no run before v0.5.1 is read.) - **Spec re-pinned to `b635b7d`** (Spec PR #37, RH1 merged; `v40`, `i140`, `i141`, `t14`, `t15` now vendored): notebook drafts saved under `69a58b3` are not carried over. +### Fixed + +- **A mask-only request on an RGB unit was refused** (`A_RGB_NOT_SUPPORTED`) unless the consumer + declared `rgb_support`, so a brick's mask-only features (MorphoObjects shapes, MorphoRelate + relations and skeletons) could not run on an RGB slide (#298). Spec `experiment-v1.md` section 8 + refuses only a request that includes the channels of an RGB unit; the resolver now counts only + the RGB images whose channels the request names. Naming one of `R`, `G`, `B` without + `rgb_support` is still refused. Owner decision of 14 November 2026: no new capability value. + ## v0.5.3 (13 November 2026) A pin release: normalization is pinned at v0.6.0, so that every core package (and CellPatcher, diff --git a/README.md b/README.md index 4c84ef6..6f5e08b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ from there. ## Status -Pre-alpha; the current release is v0.5.3 (what is planned next is in +Pre-alpha; the current release is v0.5.4 (what is planned next is in [docs/roadmap.md](docs/roadmap.md)). Implemented and tested: - Folder discovery and validation, TIFF and OME-Zarr header inspection without reading pixels @@ -61,7 +61,7 @@ converted. See the [CHANGELOG](CHANGELOG.md). ## Installation ```bash -pip install "git+https://github.com/CellMigrationLab/morphobricks-preprocessing.git@v0.5.3" +pip install "git+https://github.com/CellMigrationLab/morphobricks-preprocessing.git@v0.5.4" ``` For development, from a clone: @@ -71,7 +71,7 @@ pip install -e ".[dev]" ``` The optional `notebook` extra installs the widget dependencies for the notebook -(`pip install "morphobricks-preprocessing[notebook] @ git+https://github.com/CellMigrationLab/morphobricks-preprocessing.git@v0.5.3"`). +(`pip install "morphobricks-preprocessing[notebook] @ git+https://github.com/CellMigrationLab/morphobricks-preprocessing.git@v0.5.4"`). The notebook's first code cell (**1. Install**) can set this up automatically: it uses a compatible nearby checkout or installed package, and installs missing requirements into the active kernel. A standalone download installs from GitHub if needed (internet access and Git required). @@ -228,7 +228,7 @@ ruff format . pytest ``` -Coding conventions are described in [docs/development.md](docs/development.md). Planned work after v0.5.3 is in [docs/roadmap.md](docs/roadmap.md). +Coding conventions are described in [docs/development.md](docs/development.md). Planned work after v0.5.4 is in [docs/roadmap.md](docs/roadmap.md). ## License diff --git a/docs/colab-release-check.md b/docs/colab-release-check.md index 173b02d..217a486 100644 --- a/docs/colab-release-check.md +++ b/docs/colab-release-check.md @@ -19,7 +19,7 @@ Write the date, the commit and any failure (as an issue number) next to each ite - **Time-lapse:** a small experiment of time-lapse images (optional; the tests cover it). **Before opening it.** `RELEASE_REF` in cell 1 is the release preparation commit, and cell 3's -`PreprocessingNotebook(...)` call is that commit's API (v0.5.3: `PreprocessingNotebook()`). The +`PreprocessingNotebook(...)` call is that commit's API (v0.5.4: `PreprocessingNotebook()`). The release PR moves `RELEASE_REF` and records the pair in `RELEASE_CALLS` of `tests/test_notebook_file.py`, which fails for a `RELEASE_REF` without one. @@ -30,7 +30,7 @@ release PR moves `RELEASE_REF` and records the pair in `RELEASE_CALLS` of - [ ] One line: "… run cell 1 (Install MorphoBricks preprocessing) first …", no traceback; nothing is installed. 3. Run **cell 1**. - - [ ] It prints **Ready** with the preprocessing (0.5.3), normalization (0.6.0) and + - [ ] It prints **Ready** with the preprocessing (0.5.4), normalization (0.6.0) and ipywidgets versions and the pinned source, then names cells 2 and 3. No restart or ipywidgets upgrade is asked for; Drive is not mounted. - [ ] Run it again: nothing is installed again, the same versions. diff --git a/docs/conformance.md b/docs/conformance.md index 9927291..946744e 100644 --- a/docs/conformance.md +++ b/docs/conformance.md @@ -6,6 +6,29 @@ real run; a skip is never counted as a pass. Owner rulings of 8 November 2026 (i "no skips" applies to the Spec conformance modules (`tests/test_spec_*.py`); a skip elsewhere in the suite is listed as **not run**, with its reason. +## Release record: v0.5.4 (14 November 2026) + +A G1-style record of the v0.5.4 release candidate (as for v0.5.3 below): the RGB header override +(Spec amendment RH1, #295) and mask-only requests on RGB units (#298). Normalization stays at +v0.6.0. It does not decide a gate; deciding a gate is the owner's. + +| | | +|---|---| +| Release candidate | Measured on the tree of the v0.5.4 preparation commit (commit A of branch `claude/release-0.5.4`, from `main` at `052668e`: v0.5.3, #295 and #298) before this record was added; the record changes only this file. A keeps `RELEASE_REF` at v0.5.3's `14f6b1a`. Commit B then points the notebook's `RELEASE_REF` at A and records the pair in `RELEASE_CALLS` (the notebook and two test files only), so `git diff A B -- src pyproject.toml` is empty: the installed package is the one `RELEASE_REF` names | +| Spec pin | `tests/spec_fixtures/PIN.toml`: MorphoBricks-Spec `b635b7d5bc950529bce9dcc5681cec34b75139b8` (RH1 merged; was `69a58b3` in v0.5.3), checked by `test_spec_pin` (16 passed) | +| Environment | Linux, Python 3.13.18, the package from this tree (`PYTHONPATH=src` over an editable install of the same checkout) with `[dev,notebook,zarr]` (normalization 0.6.0 from its tag `v0.6.0` = `95e1d6d`, as pip's `direct_url.json` records; scikit-image not installed; numpy 2.5.4, tifffile 2026.11.12, ipywidgets 8.1.9, zarr 3.4.2, pytest 9.2.0); run as root on a case-sensitive file system | +| Commands | `python tools/check.py` (Ruff, Ruff format, pytest over `tests/`, code rules); `python -m pytest -q -p no:cacheprovider -rsxX tests/test_spec_*.py` | +| `tools/check.py` | Ruff clean, Ruff format 465 files already formatted, pytest **5600 passed, 4 skipped** (not run, below), 0 failed, code rules passed (exit status 0) | +| Spec modules (`tests/test_spec_*.py`) | **1839 passed, 0 skipped, 0 xfailed, 0 failed**, from all 25 modules of `tests/spec_gate.py` `EXPECTED_MODULES` (40 more than v0.5.3: the RH1 cases `v40`, `i140`, `i141`, `t14`, `t15` of the re-pinned Spec) | + +**Not run (4 environment skips, outside the Spec modules):** the four of v0.5.3 below +(`tests/test_cli_log.py:166`, `tests/test_folder_rules.py:199` and `:230`: the file system is +case-sensitive; `tests/test_discovery.py:665`: run as root). These four behaviours are **not +verified by this run**. + +**Still the owner's:** the Colab and JupyterLab browser check (`docs/colab-release-check.md`), +before tagging. + ## Release record: v0.5.3 (13 November 2026) A G1-style record of the v0.5.3 release candidate (as for v0.5.2 below), a pin release: diff --git a/notebooks/MorphoBricks_Preprocessing.ipynb b/notebooks/MorphoBricks_Preprocessing.ipynb index a302ce6..ffdb8b6 100644 --- a/notebooks/MorphoBricks_Preprocessing.ipynb +++ b/notebooks/MorphoBricks_Preprocessing.ipynb @@ -80,11 +80,11 @@ "from pathlib import Path\n", "\n", "# LabConstrictor version identifiers.\n", - "current_version = \"0.5.3\"\n", + "current_version = \"0.5.4\"\n", "notebook_name = \"MorphoBricks_Preprocessing\"\n", "\n", "# A downloaded/Colab notebook installs this immutable source revision.\n", - "RELEASE_TAG = \"v0.5.3\"\n", + "RELEASE_TAG = \"v0.5.4\"\n", "RELEASE_REF = \"14f6b1a0e37474d38f3dd54138bbfdcce69d6e9a\"\n", "REPOSITORY = \"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/CellMigrationLab/morphobricks-preprocessing.git\"\n", "EXTRAS = \"notebook\"\n", diff --git a/notebooks/notebook_latest_versions.yaml b/notebooks/notebook_latest_versions.yaml index 84f6a7d..576bbbb 100644 --- a/notebooks/notebook_latest_versions.yaml +++ b/notebooks/notebook_latest_versions.yaml @@ -1,3 +1,3 @@ # Latest version of each notebook, read by LabConstrictor's version check by notebook_name. # Equal to the notebook's current_version and its RELEASE_TAG without the "v" (README, "Notebook"). -"MorphoBricks_Preprocessing": "0.5.3" +"MorphoBricks_Preprocessing": "0.5.4" diff --git a/pyproject.toml b/pyproject.toml index dd1fb9b..c58fcdb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "morphobricks-preprocessing" -version = "0.5.3" +version = "0.5.4" description = "MorphoBricks preprocessing brick: per-plane intensity histograms and normalization methods for microscopy TIFFs." readme = "README.md" license = "MIT" diff --git a/tests/test_notebook_setup.py b/tests/test_notebook_setup.py index f073cd0..ddde857 100644 --- a/tests/test_notebook_setup.py +++ b/tests/test_notebook_setup.py @@ -105,7 +105,7 @@ def setup_environment(tmp_path, monkeypatch): drive=tmp_path / "content/drive", namespace={}, versions={ - "morphobricks-preprocessing": "0.5.3", + "morphobricks-preprocessing": "0.5.4", "morphobricks-normalization": "0.6.0", "ipywidgets": "7.7.1", }, @@ -131,7 +131,7 @@ def install(command, *, check): assert check is True state.installs.append(command) state.available.update({*REQUIRED, ZARR}) - state.versions["morphobricks-preprocessing"] = "0.5.3" + state.versions["morphobricks-preprocessing"] = "0.5.4" monkeypatch.setattr(subprocess, "run", install) @@ -163,7 +163,7 @@ def checkout_at(path): package.mkdir(parents=True) (package / "__init__.py").write_text("", encoding="utf-8") (path / "pyproject.toml").write_text( - '[project]\nname = "morphobricks-preprocessing"\nversion = "0.5.3"\n', + '[project]\nname = "morphobricks-preprocessing"\nversion = "0.5.4"\n', encoding="utf-8", ) return path @@ -179,7 +179,7 @@ def test_setup_reuses_the_matching_installed_release(setup_environment, capsys): "morphobricks_preprocessing.notebook_ui", # cell 3 shows it ] out = capsys.readouterr().out - assert "Ready: preprocessing 0.5.3" in out + assert "Ready: preprocessing 0.5.4" in out assert "ipywidgets 7.7.1" in out @@ -194,7 +194,7 @@ def test_setup_installs_missing_package_from_the_exact_commit(setup_environment, assert target.startswith("morphobricks-preprocessing[notebook] @ git+") assert target.endswith("@" + namespace["RELEASE_REF"]) assert namespace["RELEASE_REF"] == "14f6b1a0e37474d38f3dd54138bbfdcce69d6e9a" - assert "pinned v0.5.3 candidate" in capsys.readouterr().out + assert "pinned v0.5.4 candidate" in capsys.readouterr().out def test_setup_replaces_a_mismatched_installed_release(setup_environment): @@ -285,7 +285,7 @@ def test_an_explicit_development_override_uses_the_checkout_and_says_so( assert sys.path[0] == str(checkout / "src") assert f"commit {OTHER_COMMIT}, uncommitted changes" in out assert "DEVELOPMENT OVERRIDE is on" in out - assert "DEVELOPMENT OVERRIDE on" in out.split("Notebook 0.5.3")[1] + assert "DEVELOPMENT OVERRIDE on" in out.split("Notebook 0.5.4")[1] record = namespace["SETUP_RECORD"] assert record["checkout_commit"] == OTHER_COMMIT assert record["checkout_has_uncommitted_changes"] is True @@ -428,7 +428,7 @@ def test_cell_1_installs_without_mounting_drive_or_showing_the_app( assert state.apps == [] assert namespace["SETUP_RECORD"]["release_ref"] == RELEASE_REF out = capsys.readouterr().out - assert "Ready: preprocessing 0.5.3; normalization 0.6.0; ipywidgets 7.7.1." in out + assert "Ready: preprocessing 0.5.4; normalization 0.6.0; ipywidgets 7.7.1." in out assert "Next: run cell 2 (Mount Google Drive), then cell 3 (Run preprocessing)." in out @@ -444,8 +444,8 @@ def test_running_cell_1_again_installs_nothing_more(setup_environment, capsys): assert len(state.installs) == 1 assert "Installing notebook requirements" in first assert "Installing notebook requirements" not in again - assert "Ready: preprocessing 0.5.3" in again - assert state.namespace["SETUP_RECORD"]["preprocessing_version"] == "0.5.3" + assert "Ready: preprocessing 0.5.4" in again + assert state.namespace["SETUP_RECORD"]["preprocessing_version"] == "0.5.4" assert record["release_ref"] == state.namespace["SETUP_RECORD"]["release_ref"] From 2036c2ab9a4706162cbfbef9a009acba9d565b6f Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 14 Nov 2026 15:36:23 +0000 Subject: [PATCH 2/2] Point the notebook at the v0.5.4 preparation commit A RELEASE_REF = 05d763a1a0af2436957b860579a2c0636d3929de (RELEASE_TAG v0.5.4), with its PreprocessingNotebook() call recorded in RELEASE_CALLS and the test that asserts the ref: the same two-commit pattern as v0.5.3 (14f6b1a, 2ae5184). A commit cannot hold its own SHA, so the notebook installs the preparation commit, whose package code is the release's. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VbytvF3Gsa85ix8Ne2yMDW --- notebooks/MorphoBricks_Preprocessing.ipynb | 2 +- tests/test_notebook_file.py | 2 ++ tests/test_notebook_setup.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/notebooks/MorphoBricks_Preprocessing.ipynb b/notebooks/MorphoBricks_Preprocessing.ipynb index ffdb8b6..06694b1 100644 --- a/notebooks/MorphoBricks_Preprocessing.ipynb +++ b/notebooks/MorphoBricks_Preprocessing.ipynb @@ -85,7 +85,7 @@ "\n", "# A downloaded/Colab notebook installs this immutable source revision.\n", "RELEASE_TAG = \"v0.5.4\"\n", - "RELEASE_REF = \"14f6b1a0e37474d38f3dd54138bbfdcce69d6e9a\"\n", + "RELEASE_REF = \"05d763a1a0af2436957b860579a2c0636d3929de\"\n", "REPOSITORY = \"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/CellMigrationLab/morphobricks-preprocessing.git\"\n", "EXTRAS = \"notebook\"\n", "\n", diff --git a/tests/test_notebook_file.py b/tests/test_notebook_file.py index f3131d2..47e0c23 100644 --- a/tests/test_notebook_file.py +++ b/tests/test_notebook_file.py @@ -126,6 +126,8 @@ def test_notebook_uses_stable_page_api_not_a_new_app_method(): "cadbed4bb049995b2385e3b8499c8d247d3754bd": "PreprocessingNotebook()", # v0.5.3: the same call. "14f6b1a0e37474d38f3dd54138bbfdcce69d6e9a": "PreprocessingNotebook()", + # v0.5.4: the same call. + "05d763a1a0af2436957b860579a2c0636d3929de": "PreprocessingNotebook()", } CHECKOUT_CALL = "PreprocessingNotebook()" """The call of this checkout's code (every run described, no ``describe`` argument).""" diff --git a/tests/test_notebook_setup.py b/tests/test_notebook_setup.py index ddde857..628cb95 100644 --- a/tests/test_notebook_setup.py +++ b/tests/test_notebook_setup.py @@ -193,7 +193,7 @@ def test_setup_installs_missing_package_from_the_exact_commit(setup_environment, target = command[5] assert target.startswith("morphobricks-preprocessing[notebook] @ git+") assert target.endswith("@" + namespace["RELEASE_REF"]) - assert namespace["RELEASE_REF"] == "14f6b1a0e37474d38f3dd54138bbfdcce69d6e9a" + assert namespace["RELEASE_REF"] == "05d763a1a0af2436957b860579a2c0636d3929de" assert "pinned v0.5.4 candidate" in capsys.readouterr().out