WIP: Add v4 remote-module ingestion (two-phase, per-commit hooks)#6204
Draft
hjmjohnson wants to merge 15 commits intoInsightSoftwareConsortium:mainfrom
Draft
WIP: Add v4 remote-module ingestion (two-phase, per-commit hooks)#6204hjmjohnson wants to merge 15 commits intoInsightSoftwareConsortium:mainfrom
hjmjohnson wants to merge 15 commits intoInsightSoftwareConsortium:mainfrom
Conversation
Splits the v3 single-driver flow into two independent phases so the
upstream-archival publish step never runs on a working tree that
filter-repo has rewritten:
- Phase A (ingest-module-v4.sh): local, throwaway clone; rewrites
history into Modules/<Group>/<Module>; never touches the upstream
remote.
- Phase B (archive-remote-module.sh): fresh shallow clone; pushes
one removal commit + promotes MIGRATION_README.md to README.md;
flips archived=true. Gated on the Phase A PR being merged.
The shared sanitize-history.py walks the rewritten branch and applies
the same hooks ITK's .pre-commit-config.yaml enforces:
- clang-format on every C/C++ blob (content sniff)
- black on every Python blob (content sniff)
- gersemi on every CMake blob using ITK's .gersemi.config
- trailing-whitespace, end-of-file-fixer, mixed-line-ending on
every text-classified blob
- VTK / SVG / hash-content sidecar files are skipped intact
- Every commit subject without an ITK prefix gets one heuristically
auto-prepended; decisions are logged for operator audit
filter-repo's blob_callback is filename-blind by design, so excludes
are approximated via content sniffing. IOMeshSTL whitelist is the
first concrete example; smoke-tested via --dry-run successfully
(143->89 commits, 44->24 merges preserved, 108/149 blobs reformatted).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The whitelist admits whole directories (test/, wrapping/, ...) but
some upstream remote modules place CI / packaging scaffolding inside
those (e.g. test/Docker/, .github/, azure-pipelines/). Without a
deny-pass after the whitelist filter, those leak into ITK history.
Mirrors v3's --invert-paths --path-glob pass; discovered missing on
the first Cuberille v4 ingest (test/Docker/{Dockerfile,build,run,test}.sh
leaked).
dzenanz
reviewed
May 4, 2026
| @@ -0,0 +1,25 @@ | |||
| # IOMeshSTL — files that migrate into ITK at Modules/IO/MeshSTL/ | |||
Member
There was a problem hiding this comment.
Is there reason this list is kept per remote?
| @@ -0,0 +1,539 @@ | |||
| #!/usr/bin/env python3 | |||
| """sanitize-history.py — Apply ITK formatting and commit-prefix conventions | |||
Member
There was a problem hiding this comment.
It feels like "sanitize history" script already exists somewhere.
Fixes the four classes of ghostflow errors that surfaced on the first Cuberille v4 ingest (PR InsightSoftwareConsortium#6205) — the only allowable remaining error should be the unavoidable upstream root commit. - Strip *.orig / *.rej / *.BACKUP.* / *.LOCAL.* / *.REMOTE.* / *.BASE.* merge-conflict-artifact files from history (catches leftover-conflict-marker errors like the .h.orig on Cuberille). - sanitize-history.py: cap every commit subject at 78 chars (ghostflow / kw-commit-msg rule); excess words move into the body. - sanitize-history.py: insert a blank line between subject and body when the original commit message lacked one (two-line subject error). - sanitize-history.py: clear the executable bit (mode 100755 -> 100644) on text-file extensions so root-commit "executable permissions but file does not look executable" stops firing.
Many ITK remote modules' itk-module.cmake reads
file(READ "${MY_CURRENT_DIR}/README.rst" DOCUMENTATION)
to populate the CMake DESCRIPTION variable from the upstream README.
The v4 whitelist intentionally excludes the upstream README (the
operator ships a new README.md as part of the ingest PR), so without
this rewrite every commit's CMakeLists fails to configure post-ingest
until the operator manually patches itk-module.cmake.
sanitize-history.py now rewrites the file(READ ... README.rst ...)
reference to README.md as part of the cmake-blob transform, so every
historical commit on the rewritten branch is independently buildable.
Surfaced on the IOMeshSTL ingest (PR following PR InsightSoftwareConsortium#6204).
This was referenced May 4, 2026
…terns
Add a 'Known artifacts at PR-review time' section to capture two
things future ingest operators need to expect but that v3/v4 do not
fix automatically:
- The single ghostflow-check-main 'root commit not allowed' error
that every Mode-A merge produces. Maintainers override at merge.
Calling it out keeps operators from chasing a non-fix.
- A short table of code-level patterns Greptile has flagged
post-ingest on multiple modules (IOMeshSTL InsightSoftwareConsortium#6206, RLEImage InsightSoftwareConsortium#6208):
signed-vs-unsigned size types, missing override, dead return after
itkExceptionMacro, stray test args, external-friend declarations,
GetBuffer-const correctness, and allocator-init invariants.
The table is the durable channel for cross-ingest review knowledge —
extend it as new recurring patterns surface.
ExternalData stores resolved fetched content as .ExternalData_<algo>_<hash> files alongside the .cid / .md5 sidecars they correspond to. These are local fetch cache, not source — ExternalData regenerates them on demand at consumer-time. Upstream remote modules sometimes commit them inadvertently from a CTest run inside their working tree (e.g. ITKIOMeshSTL had four such files in test/Baseline/, flagged by @dzenanz on PR InsightSoftwareConsortium#6206). Add **/.ExternalData_* to the scaffolding deny-pass so they never enter ITK history.
Upstream remote modules wrap their top-level CMakeLists.txt in
if(NOT ITK_SOURCE_DIR)
find_package(ITK REQUIRED)
list(APPEND CMAKE_MODULE_PATH ${ITK_CMAKE_DIR})
include(ITKModuleExternal)
else()
itk_module_impl()
endif()
so the same file works both as a fetched remote module and as a
stand-alone CMake project. In an in-tree ingested module
ITK_SOURCE_DIR is always defined, so the if-branch is dead code;
@dzenanz flagged it on PR InsightSoftwareConsortium#6206 (IOMeshSTL).
Add patch_standalone_build_guard() that detects the idiom (allowing
2- or 4-space indent variants) and replaces it with a bare
itk_module_impl() before gersemi formatting runs. Track count via
sanitizer.standalone_guard_patches and print it in the run summary.
The 'Greptile post-ingest patterns' table mixed mechanical artifacts (strippable in Phase A) with semantic concerns (require human judgment). Split into two sections so the operator's checklist shrinks as the sanitizer learns more rules. Promote .ExternalData_* and the standalone-build CMake guard to the auto-sanitized table now that the previous two commits handle them.
50 tasks
Upstream remote modules typically begin their top-level CMakeLists.txt with their own cmake_minimum_required(VERSION X.Y.Z) declaration, often 3.10.2 or earlier. ITK's top-level CMakeLists pins a higher minimum, so the per-module line is redundant and frequently *lower* than ITK's floor. @dzenanz flagged it on every ingest with the comment 'Version behind, not needed.' — most recently on PR InsightSoftwareConsortium#6215 (IOFDF). Add patch_drop_cmake_minimum_required() that detects the idiom and removes the matching line via a multiline regex. Track count via sanitizer.cmake_min_required_drops and print it in the run summary. Apply alongside patch_standalone_build_guard() in the cmake-blob branch of blob_callback.
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 5, 2026
….txt In-tree, ITK's top-level CMakeLists pins the CMake minimum, so the per-module declaration is dead code. Pre-emptive cleanup matching the v4 ingest-pipeline rule codified in PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 5, 2026
…mage In-tree, ITK_SOURCE_DIR is always defined and ITK's top-level CMakeLists pins the CMake minimum version. The per-module cmake_minimum_required line and if(NOT ITK_SOURCE_DIR) ... else() itk_module_impl() endif() guard are dead code. Pre-emptive cleanup matching the v4 ingest-pipeline rules codified in PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required and :patch_standalone_build_guard).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 5, 2026
In-tree, ITK's top-level CMakeLists pins the CMake minimum, so the per-module declaration is dead code. Matches the v4 ingest-pipeline rule in PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 5, 2026
In-tree, ITK's top-level CMakeLists pins the CMake minimum, so the per-module declaration is dead code. Matches the v4 ingest-pipeline rule in PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 5, 2026
…shMZ3
In-tree, ITK_SOURCE_DIR is always defined and ITK's top-level
CMakeLists pins the CMake minimum version. The per-module
cmake_minimum_required line and if(NOT ITK_SOURCE_DIR) ... else()
itk_module_impl() endif() guard are dead code. The 'set(ITK_DIR
${CMAKE_BINARY_DIR})' line that was inside the in-tree else branch
is preserved (now unconditional) since it actually had effect during
the in-tree build path. Matches the v4 ingest-pipeline rules in
PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required and
:patch_standalone_build_guard).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 5, 2026
…shMZ3
In-tree, ITK_SOURCE_DIR is always defined and ITK's top-level
CMakeLists pins the CMake minimum version. The per-module
cmake_minimum_required line and if(NOT ITK_SOURCE_DIR) ... else()
itk_module_impl() endif() guard are dead code. The 'set(ITK_DIR
${CMAKE_BINARY_DIR})' line that was inside the in-tree else branch
is preserved (now unconditional) since it actually had effect during
the in-tree build path. Matches the v4 ingest-pipeline rules in
PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required and
:patch_standalone_build_guard).
hjmjohnson
added a commit
that referenced
this pull request
May 5, 2026
Four already-merged remote-module ingests still carry their
upstream-original boilerplate at the top of their module CMakeLists:
- cmake_minimum_required(VERSION X.Y.Z) — redundant; ITK's top-level
CMakeLists pins a higher minimum.
- if(NOT ITK_SOURCE_DIR) ... find_package(ITK) ... else()
itk_module_impl() endif() — dead code in-tree because
ITK_SOURCE_DIR is always defined.
Strip both from:
Modules/Filtering/AnisotropicDiffusionLBR
Modules/Filtering/Cuberille
Modules/Filtering/LabelErodeDilate
Modules/Registration/Montage
Lines that had effect inside the in-tree else() branch
(set(ITK_DIR ${CMAKE_BINARY_DIR}) on AnisotropicDiffusionLBR and
Montage) are preserved unconditionally.
The other four merged ingests (GenericLabelInterpolator, MGHIO,
FastBilateral, MeshNoise) were already cleaned up during their
respective ingest PRs.
Matches the v4 ingest-pipeline rules now codified in PR #6204
(sanitize-history.py:patch_drop_cmake_minimum_required and
:patch_standalone_build_guard); future ingests will not introduce
this idiom.
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 5, 2026
…mage In-tree, ITK_SOURCE_DIR is always defined and ITK's top-level CMakeLists pins the CMake minimum version. The per-module cmake_minimum_required line and if(NOT ITK_SOURCE_DIR) ... else() itk_module_impl() endif() guard are dead code. Pre-emptive cleanup matching the v4 ingest-pipeline rules codified in PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required and :patch_standalone_build_guard).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 5, 2026
…mage In-tree, ITK_SOURCE_DIR is always defined and ITK's top-level CMakeLists pins the CMake minimum version. The per-module cmake_minimum_required line and if(NOT ITK_SOURCE_DIR) ... else() itk_module_impl() endif() guard are dead code. Pre-emptive cleanup matching the v4 ingest-pipeline rules codified in PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required and :patch_standalone_build_guard).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 5, 2026
In-tree, ITK's top-level CMakeLists pins the CMake minimum, so the per-module declaration is dead code. Matches the v4 ingest-pipeline rule in PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 6, 2026
In-tree, ITK's top-level CMakeLists pins the CMake minimum, so the per-module declaration is dead code. Matches the v4 ingest-pipeline rule in PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 6, 2026
Four already-merged remote-module ingests still carry their
upstream-original boilerplate at the top of their module CMakeLists:
- cmake_minimum_required(VERSION X.Y.Z) — redundant; ITK's top-level
CMakeLists pins a higher minimum.
- if(NOT ITK_SOURCE_DIR) ... find_package(ITK) ... else()
itk_module_impl() endif() — dead code in-tree because
ITK_SOURCE_DIR is always defined.
Strip both from:
Modules/Filtering/AnisotropicDiffusionLBR
Modules/Filtering/Cuberille
Modules/Filtering/LabelErodeDilate
Modules/Registration/Montage
Lines that had effect inside the in-tree else() branch
(set(ITK_DIR ${CMAKE_BINARY_DIR}) on AnisotropicDiffusionLBR and
Montage) are preserved unconditionally.
The other four merged ingests (GenericLabelInterpolator, MGHIO,
FastBilateral, MeshNoise) were already cleaned up during their
respective ingest PRs.
Matches the v4 ingest-pipeline rules now codified in PR InsightSoftwareConsortium#6204
(sanitize-history.py:patch_drop_cmake_minimum_required and
:patch_standalone_build_guard); future ingests will not introduce
this idiom.
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 6, 2026
….txt In-tree, ITK's top-level CMakeLists pins the CMake minimum, so the per-module declaration is dead code. Pre-emptive cleanup matching the v4 ingest-pipeline rule codified in PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 6, 2026
…shMZ3
In-tree, ITK_SOURCE_DIR is always defined and ITK's top-level
CMakeLists pins the CMake minimum version. The per-module
cmake_minimum_required line and if(NOT ITK_SOURCE_DIR) ... else()
itk_module_impl() endif() guard are dead code. The 'set(ITK_DIR
${CMAKE_BINARY_DIR})' line that was inside the in-tree else branch
is preserved (now unconditional) since it actually had effect during
the in-tree build path. Matches the v4 ingest-pipeline rules in
PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required and
:patch_standalone_build_guard).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 6, 2026
…mage In-tree, ITK_SOURCE_DIR is always defined and ITK's top-level CMakeLists pins the CMake minimum version. The per-module cmake_minimum_required line and if(NOT ITK_SOURCE_DIR) ... else() itk_module_impl() endif() guard are dead code. Pre-emptive cleanup matching the v4 ingest-pipeline rules codified in PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required and :patch_standalone_build_guard).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 6, 2026
In-tree, ITK's top-level CMakeLists pins the CMake minimum, so the per-module declaration is dead code. Matches the v4 ingest-pipeline rule in PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required).
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 6, 2026
In-tree, ITK's top-level CMakeLists pins the CMake minimum, so the per-module declaration is dead code. Matches the v4 ingest-pipeline rule in PR InsightSoftwareConsortium#6204 (sanitize-history.py:patch_drop_cmake_minimum_required).
…cmake
Archival README.md files contain semicolons and bracket characters.
CMake's foreach(arg \${ARGN}) splits on semicolons, so reading them
into a DESCRIPTION argument produces CMake (dev) configure warnings
for every module ingested via v4 (observed: RLEImage, SplitComponents,
IOFDF, IOMeshMZ3, IOMeshSTL).
Add patch_dynamic_description() to sanitize-history.py to strip the
get_filename_component/file(READ README.md) preamble and replace
DESCRIPTION "\${DOCUMENTATION}" with a static one-liner during history
rewrite. Document the pattern in INGESTION_STRATEGY_v4.md.
This was referenced May 6, 2026
hjmjohnson
added a commit
to hjmjohnson/ITK
that referenced
this pull request
May 7, 2026
Many ITK remote modules' itk-module.cmake reads
file(READ "${MY_CURRENT_DIR}/README.rst" DOCUMENTATION)
to populate the CMake DESCRIPTION variable from the upstream README.
The v4 whitelist intentionally excludes the upstream README (the
operator ships a new README.md as part of the ingest PR), so without
this rewrite every commit's CMakeLists fails to configure post-ingest
until the operator manually patches itk-module.cmake.
sanitize-history.py now rewrites the file(READ ... README.rst ...)
reference to README.md as part of the cmake-blob transform, so every
historical commit on the rewritten branch is independently buildable.
Surfaced on the IOMeshSTL ingest (PR following PR InsightSoftwareConsortium#6204).
dzenanz
approved these changes
May 7, 2026
Member
dzenanz
left a comment
There was a problem hiding this comment.
As this is all in the maintenance directory, I believe we can accept it without really reviewing it.
hjmjohnson
added a commit
that referenced
this pull request
May 7, 2026
…shFilter ENH: Ingest ITKSubdivisionQuadEdgeMeshFilter into Modules/Filtering (v4, stacks on #6204)
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.
This PR is a WIP because each new remote module adds minor new elements that need to be addressed.
Adds a v4 remote-module ingestion pipeline that splits the v3 single-driver flow into two independent phases — Phase A is fully local and reversible; Phase B publishes to upstream only after the Phase A PR has merged on ITK
main. Each historical commit is individually re-formatted (clang-format / black / gersemi / trailing-ws / EOF / line-ending) and retroactively conformed to ITK ghostflow rules (subject ≤78 chars, blank line after subject, exec-bit cleared on text files), so every historical commit independently passes ITK's CI gates after the merge.WIP — opening for design feedback. Validated end-to-end on Cuberille (PR #6205): ghostflow now reports a single, unavoidable error (the upstream root commit). All other categories (long subjects, conflict markers in
.orig, exec-bit onCMakeLists.txt, two-line subjects) are eliminated.Why two phases (motivation)
In v3 (
ingest-remote-module.sh) the script orchestrated upstream archival as a bonus step at the end of the ingest. Re-running the ingest after a CI failure risked re-touching the upstream remote, and the upstream-archival step was a manual checklist (perfeedback_ingest_archive_readme.md) — easy to forget steps.v4 splits these into two independent phases:
ingest-module-v4.sharchive-remote-module.shMIGRATION_README.mdtoREADME.md+ flipsarchived=trueThe phases share one persistent artifact: the whitelist at
Utilities/Maintenance/RemoteModuleIngest/whitelists/<Module>.list. Every other piece of state is reproducible.The central correctness property: upstream is never touched until ITK has accepted the migration.
Per-commit hook + ghostflow coverage
sanitize-history.pywalks every commit on the rewritten ingestion branch viagit_filter_repo'sblob_callback+commit_callback. Becauseblob_callbackis filename-blind by design (blobs stream before commits), the filter mirrors ITK's pre-commit excludes via content sniffing. For typical module ingests, the upstream whitelist has already prunedThirdParty/,Data/,build/, andpixi/paths, so the exclude set narrows to a handful of content-detectable extensions.clang-format(.c .cc .cxx .h .hxx)#include,#pragma,namespace itk,template <, ... in first 8K bytesblack(.py)import/from/def/classgersemi(.cmake .wrap CMakeLists.txt)cmake_minimum_required,project(,add_library(, ITK macros (itk_module_*,itk_add_test,itk_wrap_*)trailing-whitespaceend-of-file-fixermixed-line-ending(CRLF→LF)check-shebang-scripts-are-executabletruncate_subject_to_body()— excess moves to commit body, preferring word-breakensure_blank_line_after_subject()— inserts\nif missing*.orig,*.rej,*.BACKUP.*,*.LOCAL.*,*.REMOTE.*,*.BASE.*from all historycommit_callbackwalksfile_changesand clears mode100755 → 100644for known text extensionsDockerfile*,.github/*,.travis.yml,azure-pipelines*,circle.yml,.gitlab-ci.yml,appveyor.yml,pyproject.toml,setup.py, etc.Heuristic commit-prefix mapping
When a historical commit subject does not start with a recognized ITK prefix (
BUG:/COMP:/DOC:/ENH:/PERF:/STYLE:/WIP:),sanitize-history.pyauto-prepends one based on the table below. Every decision is logged with<sha> <chosen-prefix> <original-subject>so the operator can audit before merge.fix,bug,crash,segfault,leak,regression,corrupt,deadlockBUG:cmake,compil,warning,build,ci/ci:,clang,gcc,msvcCOMP:doc,readme,comment,license,sphinx,doxygenDOC:style,whitespace,format,rename,lint,clean up,reorderSTYLE:perf,optim,speed,faster,efficienPERF:ENH:(default)These rules are conservative — when in doubt, default to
ENH:. Misclassifications get caught by the operator reading the sidecar log.Smoke-test 1: IOMeshSTL (--dry-run)
Topology preserved (44→24 merges; non-zero, no linearization).
Smoke-test 2: Cuberille (real ingest, PR #6205) — proves ghostflow conformance
PR #6205 stacks on this PR and is the first real consumer. Ghostflow on PR #6205 reports exactly one error:
That's the only remaining failure mode — the upstream module's genesis commit. All four other ghostflow categories that originally fired on Cuberille (long subjects on 6 commits, conflict markers in
.h.origon commitd23f9207, exec-bit onCMakeLists.txtin the root commit, two-line subject on6127d75f41) are gone after this PR's hardening landed.Sanitize-history.py counters from the Cuberille run that demonstrate the hardening is doing real work:
Build + 25/25 Cuberille tests pass locally.
Files added
Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY_v4.md— design documentUtilities/Maintenance/RemoteModuleIngest/ingest-module-v4.sh— Phase A driverUtilities/Maintenance/RemoteModuleIngest/archive-remote-module.sh— Phase B driverUtilities/Maintenance/RemoteModuleIngest/sanitize-history.py—git_filter_repocallback driverUtilities/Maintenance/RemoteModuleIngest/whitelists/IOMeshSTL.list— first concrete whitelist (smoke-test target)The v3 scripts (
ingest-remote-module.sh,normalize-ingest-commits.py, etc.) are intentionally retained in tree until v4 has been used for two successful ingests.Open questions for reviewers
Gersemi version drift. Local install is 0.24.0; ITK pre-commit pins 0.19.3. Confirmed in practice on Cuberille: the post-merge
pre-commit run --all-filesgate catches one CMake file per ingest where the two versions disagree, fixed via aSTYLE:follow-up commit. Acceptable, or should v4 verify version match before running?Subject truncation can fall mid-word when a long word starts before offset 40 (e.g.
STYLE: Merge pull request #21 from jhlegarreta/ImproveCuberilleImageToMeshFiltlost theerStylesuffix). The full original subject is preserved in the body, but the visible subject is uglier. Reviewer preference for raising the word-break minimum, or accept ghostflow-clean-but-cosmetically-truncated?check-shebang-scripts-are-executableis currently deferred. Acceptable post-merge gate, or worth adding now?