Repository navigation
feat: Windows on ARM64 (NVIDIA RTX Spark) support; replace passlib with bcrypt 5 - #9860
Conversation
Adds a dispatch-only workflow that builds opencv-contrib-python, blake3 and tiktoken on the windows-11-arm runner and attaches them, with a flat index page, to a GitHub release for pyproject's Windows ARM64 sources to consume. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiaFTnYH9q9468Naf4PV3X
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiaFTnYH9q9468Naf4PV3X
Windows ARM64 has no wheels for mediapipe's legacy solutions API, numba or passlib-compatible bcrypt. Face nodes import lazily and name the platform when used, the image map falls back to a PCA projection without umap-learn, password hashing calls bcrypt directly, bitsandbytes guards survive a build whose native library fails to load, and startup logs the torch build. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiaFTnYH9q9468Naf4PV3X
check_aarch64_lock.py becomes check_platform_locks.py: the aarch64 check is unchanged, and win32/ARM64 additionally requires torch from NVIDIA's index and a win_arm64 wheel for every package in the closure. python-tests gains a 3.12-only windows-11-arm lane. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiaFTnYH9q9468Naf4PV3X
pyproject forks the packages whose Windows ARM64 wheels start at newer versions, routes torch to NVIDIA's out-of-tree index and OpenCV, blake3 and tiktoken to the release-hosted wheel page on that platform, and enforces ARM64 wheel availability with uv's required-environments. Docs cover the native ARM64 Python request, the install options and the feature differences. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiaFTnYH9q9468Naf4PV3X
MSVC has no __fp16 type, which the DNN Winograd kernel uses once NEON_FP16 is in the CPU baseline; pin the baseline to NEON with DOTPROD dispatch. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiaFTnYH9q9468Naf4PV3X
Adds the win32/ARM64 resolution: torch 2.14.0+cu134 from NVIDIA's index, the release-hosted opencv/blake3/tiktoken wheels, and the ARM64-capable versions of numpy, onnx, onnxruntime, sentencepiece, bitsandbytes, cryptography and PyWavelets. Other platforms change only by bcrypt 5.0.0 replacing passlib. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiaFTnYH9q9468Naf4PV3X
Skip the woff2 font test where brotli is absent, name the platform in the MediaPipe error only on Windows ARM64, cover transitive/extra/sdist paths in the lock checker tests, and correct the platform docs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiaFTnYH9q9468Naf4PV3X
Pull-request runs of the wheel workflow only build and verify; publishing is dispatch-only under a concurrency group, and tags are treated as immutable because the lockfile pins the assets by hash. The closure walk now follows a package's extras even after a plain edge reached it, the ARM64 test lane skips uv's cache, and the umap fallback is a cached loader. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiaFTnYH9q9468Naf4PV3X
The windows-arm64 lane imports the self-built wheels explicitly (tiktoken is never imported by the suite), and the platform lock checker walks the test extra the lane installs and reports edges the lock cannot resolve. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiaFTnYH9q9468Naf4PV3X
NVIDIA's ARM64 torch dies with an access violation in torch.cuda.is_current_stream_capturing() when no CUDA device is present, which transformers calls on every forward pass. Answer False there, at app startup and in the test session. Also split the SDPA pass-through test: torch 2.14 rejects an explicit mask together with is_causal=True. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiaFTnYH9q9468Naf4PV3X
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiaFTnYH9q9468Naf4PV3X
…x-spark # Conflicts: # .github/workflows/python-tests.yml # invokeai/app/services/image_index/projection.py # scripts/check_aarch64_lock.py # uv.lock
Upstream's torch 2.13/cu130, ROCm 10 (now also on Windows), constraint-dependencies and database-layer changes, with every new win32 marker narrowed to x64 and the ARM64 fallbacks added; onnx 1.21 and sentencepiece 0.2.2 now serve both platforms, so their ARM64 forks go.
The optional-import guards record the first failure and log it once; the loaders' error carries it instead of asking to install a package that is installed.
… platform Missing mediapipe, numba or brotli is tolerated only on Windows ARM64, and the shim no longer leaks into the rest of the suite. Docs cover the x64-Python update failure and the patchmatch startup error on ARM64.
|
@Pfannkuchensack thanks for the thorough review. I confirmed each point against the code before fixing it. Everything is in 3752285..9a2823d, and each fix has a regression test that fails against the old code. Before merge
Should fix
Minor
Checks:
|
There was a problem hiding this comment.
Thanks for the quick turnaround. I re-reviewed head 9a2823d. Almost everything from my first pass is resolved:
- Wheels: they're hosted here now.
win-arm64-wheels-v1digests match the lock, and only URLs changed. - Publish workflow: it requires a new tag and
--clobberis gone.plan_release_upload.pyrefuses on any difference, and the protectedwin-arm64-wheelsenvironment andpermissions: contents: readare in place. - Image map: the PCA fallback is ARM64-only, records the method in the params, refits once UMAP imports, and uses the D×D scatter matrix. That's about 0.17 GB extra at 300k points, down from 2.5 GB at 100k before.
- bitsandbytes: guards now log the real failure and carry it into the loader error.
- Tests and checker: x64 skips are confined to ARM64, the conftest shim only installs there, the PCA cache leak is gone, and the aarch64 check again requires a per-extra pin.
- Disclosure and docs: the bitsandbytes xpu change is disclosed, and the FAQ and patchmatch docs are added.
Locally, ruff, uv lock --locked, check_platform_locks.py and check_pins.py pass, along with the focused tests (also with bcrypt 5). The old-vs-new lock comparison again differs only in bcrypt/passlib and bitsandbytes for the xpu extra.
Still blocking
- The
py3.12: windows-arm64lane times out on both heads. Runs 38663611897 and 38676871057 were both cancelled at the 60-minute job timeout at about 74 %. Both show the same 8 failures on the 73 % progress line (...FFF.FFF.......FF...), and the progress has 5–8 minute gaps, so something is hanging or very slow. Because the job is cancelled before pytest prints its summary, the failing tests can't be identified from the log. Adding-rf, a junit report, or a per-test--timeoutwould surface them. The lane numbers in the description ("every check green", 13 min) come from InvokeAI-7, not from this repo. - The merge with current main breaks the test suite. The textual conflict is only in
.github/AGENTS.md(after #9863). The semantic one is intests/conftest.py: since #9859, main's_cheap_password_hashingandproduction_password_hashingpatchpassword_utils.pwd_context, which this PR removes. After the merge, collection fails. Yourhash_passwordreadsBCRYPT_ROUNDSon each call, so the fix is simple: patchpassword_utils.BCRYPT_ROUNDSto 4 in the autouse fixture and restore 12 inproduction_password_hashing. Also keeptest_hashing_cost_stays_at_a_defensible_work_factoronproduction_password_hashing. When resolvingpython-tests.yml, don't copy windows-cpu'snot platform_independentmarker to the ARM64 entry; ARM64 has its own dependency set, so it should run those tests.
Minor
.github/AGENTS.mdplacement: since #9863 it's a terse policy file. One or two policy lines (the gate blocks; the options are a fork pin, a marker exclusion with a system-requirements entry, or a self-built wheel) would fit. The dispatch/retag/relock procedure is better kept in the workflow header or indocs/.../development/.- Two-way method check:
projection_method_is_currenttreats any mismatch as stale. On ARM64, a valid UMAP map (a database copied from x64, or a legacy row without the field) gets replaced by PCA. Treating only storedpcawith UMAP available as stale avoids that. - Thread hop:
image_map.pynow callsasyncio.to_thread(projection_method_is_current, …)on every/pointscall on every platform. Doing it inline unlessis_windows_arm64()would skip that. - Partial uploads: the workflow header says "re-run failed jobs" completes an interrupted upload. An upload that dies mid-asset can leave a digest-less asset, which the planner (correctly) refuses, so a manual delete is needed. A note in the header would help.
- Still open from last time:
- test vectors for >72-byte and
$2a$/$2y$legacy passwords; - the "protobuf mismatch" comment in
mediapipe_face/__init__.py(that failure raisesTypeError, notImportError); - the mediapipe gate test patching global
sys.platform(patchingmediapipe_face.is_windows_arm64would be narrower); - the production shim scope and docstring;
- the tab labels in
manual.mdx; ${{ matrix.* }}interpolated into arun:step in the wheel workflow.
- test vectors for >72-byte and
The cheap-hashing test fixtures from main now patch password_utils.BCRYPT_ROUNDS, since this branch replaces passlib's pwd_context with bcrypt; the lock-gate runbook shrinks to one policy line in .github/AGENTS.md, with the procedure in the wheel workflow's header.
Image map: only a stored PCA map goes stale once UMAP imports; the method check skips the thread hop off ARM64. The stream-capture shim installs only on Windows ARM64; bcrypt tests cover >72-byte and $2a$/$2y$ passlib hashes; the wheel workflow passes matrix values through env and pins setup-uv.
…timeout On Windows ARM64 the ffmpeg on PATH can be a Chocolatey or Scoop shim; killing only the shim left the real binary running (an endless anullsrc in the test suite pegged the ARM64 runner's CPU). The upload conversion now runs through the same tree-killing runner.
…ackend The Windows ARM64 OpenCV wheel decodes through Media Foundation, whose frame count comes from the container duration, so a soundtrack outlasting the video doubled it. The decode worker now counts the video stream's packets with ffmpeg there.
|
Thanks for the second pass. Here is where each item stands; head is Blocking
Minor
Known gapThe two ffmpeg probe calls ( |
|
Thanks, that all checks out on
A few small things left, none of them big:
Separately, for the launcher: OSSign/invoke-ai-launcher#3 was merged at 0a9ff2d without the VS 2022 Build Tools step or |
Pfannkuchensack
left a comment
There was a problem hiding this comment.
Re-reviewed 44b63e6876, still on x64 only. Approving: both blockers from my second pass are fixed, and everything else from my first two passes is in. Two small items from my last comment are still open (inline), plus a few nits.
Earlier points
| Point | Status | Evidence |
|---|---|---|
| joshistoast's asset replacement / my P1-2 | Resolved | release_tag is required with no default, --clobber is gone, plan_release_upload.py refuses differing or digest-less assets, permissions: contents: read, publish job in win-arm64-wheels |
| P1-1 archived wheel repo | Resolved | The index points at win-arm64-wheels-v1 in this repo |
| P1-3 x64 Python on ARM64 | Resolved (docs) | FAQ entry and system requirements; release order in the description |
P1-4 bitsandbytes for xpu |
Disclosed | The only non-ARM64 change besides bcrypt/passlib (see below) |
| P1-5 PCA fallback | Resolved | ARM64 only, method recorded, chunked D×D scatter + eigh |
| P1-6 test guards | Resolved | mediapipe, numba and brotli allowances gated on is_windows_arm64() |
| P1-7 test isolation | Resolved | _umap_hidden clears on exit, conftest shim ARM64-only, shim test uses a fresh stand-in |
| P1-8 bitsandbytes error | Resolved | bnb_import.py; the loaders raise the recorded cause |
| P1 minors | Resolved | Runbook line, NVIDIA risk, title, per-extra aarch64 pin, stale text, patchmatch |
| P2-1 ARM64 lane timeout | Resolved | The orphaned anullsrc behind Chocolatey's shim is fixed by the tree kill, the doubled frame counts by the packet count; lane green at 36 of 60 min |
| P2-2 merge with main | Resolved | BCRYPT_ROUNDS fixtures, cost test on production_password_hashing, ARM64 entry runs platform_independent |
| P2 minors | Resolved | One-way method check, inline check off ARM64, partial-upload note, legacy vectors, comment, gate test, shim scope, tab label, matrix.* through env: |
| P3-1 shim test | Open | Inline |
| P3-2 tree kill | Open | Inline |
| P3-3 packet-count timeout | Fine as is | Bounded by the worker's 30 s budget and its tree kill |
| P3-4 history | At merge | See below |
Before merging
- Squash away the two "temporarily sample" commits and drop the
Co-Authored-By/Claude-Session:trailers from the squash message. - joshistoast's CHANGES_REQUESTED review is still on record; it needs their re-review or a dismissal.
- Add required reviewers to the
win-arm64-wheelsenvironment in the repository settings. Until then a dispatch publishes without approval.
Verified
- Passwords: I generated hashes with the former passlib 1.7.4 + bcrypt 3.2.2 code for nine passwords (ASCII, unicode, emoji, exactly 72 and 73 bytes, over 72 with a UTF-8 character split at byte 72, 200 bytes), each as
$2b$,$2a$and$2y$. All 27 verify on this branch under bcrypt 5.0.0, a changed first character never does, and hashes from this branch verify under the old passlib code, so a rollback keeps working. Inputs over 72 bytes don't raise (bcrypt 5's ownhashpw/checkpwdo, so the truncation is load-bearing), and empty or malformed hashes return False. One small difference: passlib rejected passwords containing NUL; bcrypt 5 hashes them in full. - Lockfile: comparing base and head per platform (Linux x86_64/aarch64, Windows x64, macOS arm64/x86_64, every extra combination; versions, sources and hashes), the only changes are bcrypt 3.2.2 → 5.0.0, passlib removed, and bitsandbytes 0.49.2 → 0.50.2 for
xpuon Linux x86_64 and Windows x64. ruff,check_platform_locks.pyand the focused suites pass locally; the auth and multiuser suites also under bcrypt 5.
Follow-ups, not blocking
- #9856 on main:
video_smart_concat.encode_rgb_frameslanded after this branch's last merge and kills only its direct child on cancel or timeout. Behind a shim on ARM64 the real ffmpeg keeps encoding until it reads EOF on stdin, so it ends on its own, and the tests mock it. Worth adding to the follow-up with the two probes. - nit: the description still says in a few places that nothing changed outside ARM64 ("exactly as before apart from one deliberate change", "no other package's version or wheel list changed"), while the compatibility section correctly lists the
xpubitsandbytes bump.
…ndable The ffmpeg runner and the thumbnail worker now use one helper that lists children even when suspending the root is denied, and skips an already-reaped process. The shim test warms imageio's binary lookup first and tracks ffmpeg by identity.
… CI ffmpeg Without brotli a WOFF2 upload now says the format is unsupported here rather than that the font is invalid. bcrypt is bounded <6; the ARM64 lane installs ffmpeg 9.0.2.
|
Thanks for the approval. Head is
|
Summary
Moved from invoke-ai#261 and merged up to this repository's
main(torch 2.13 / cu130, ROCm 10 on Windows, the database layer). Every new upstreamwin32marker is narrowed to x64 so Windows ARM64 keeps NVIDIA's torch in every extra.Invoke could not be installed on Windows on ARM64 (NVIDIA's RTX Spark developer preview): every marker treated
win32as x64, the lockfile carried onlywin_amd64wheels, and several dependencies have no ARM64 build at the pinned versions. With this PR,uv sync --frozenanduv pip installon a native ARM64 Python 3.12 produce a working install with NVIDIA's torch 2.14.0+cu134 (fromhttps://pypi.nvidia.com/nvtorch_oot/), CI proves it on GitHub'swindows-11-armrunners, and other platforms resolve as before apart from two changes: bcrypt 5 replaces passlib, and thexpuextra moves to the bitsandbytes version the other extras already use.How it fits together:
pyproject.tomlforks the packages whose ARM64 wheels start at newer versions (numpy2.3,onnxruntime1.24,bitsandbytes0.50.1,PyWavelets1.10;main's onnx 1.21.0 and sentencepiece 0.2.2 already have ARM64 wheels, and its move to PyJWT removed the cryptography 46.0.x pin python-jose needed) behindsys_platform == 'win32' and platform_machine == 'ARM64', routes torch/torchvision to NVIDIA's index there for every extra, and sets uv'srequired-environmentsso a wheel-only package without an ARM64 wheel fails at lock time.windows-11-armand publishes them, with a flatindex.html, as assets of releasewin-arm64-wheels-v1in this repository (byte-identical copies of the wheels first built in the now-archived InvokeAI-7); pyproject consumes that page as a flat index and pins the exact versions so the manual--find-linkspath prefers the wheels over PyPI's sdists. Pull-request runs of that workflow only build and verify. Published tags are immutable because the lockfile pins the assets by hash: a dispatch must name a newrelease_tag(no default), the publish job runs in thewin-arm64-wheelsenvironment, and it never replaces an asset — it uploads only names the release lacks, skips identical ones (so "Re-run failed jobs" can finish an interrupted upload) and fails on any other difference.scripts/check_aarch64_lock.pybecomesscripts/check_platform_locks.py: linux/aarch64 still requires every extra to carry its own aarch64 torch pin, and win32/ARM64 additionally requires torch from NVIDIA's registry and walks the whole dependency closure forwin_arm64wheels (uv'srequired-environmentscannot see packages that also publish an sdist). The closure check blocks: every dependency bump must keep awin_arm64(or pure) wheel;.github/AGENTS.mddescribes the options when it fires.solutionsAPI on ARM64) and umap/numba (no wheel for 3.12) are excluded there; the face nodes import mediapipe lazily and name the platform when it is the cause, the image map falls back to a PCA projection on Windows ARM64 only (elsewhere a failed umap import is a failed fit; the stored params record the method, so a PCA map is refit once umap imports), password hashing calls bcrypt directly (passlib 1.7 cannot use bcrypt >= 4.1, the first release with ARM64 wheels), the bitsandbytes guards survive a build whose native library fails to load and log the real error once (the loaders' error carries it), and startup logs the torch build and host architecture. One shim is specific to NVIDIA's build: without a CUDA device it dies with an access violation intorch.cuda.is_current_stream_capturing(), which transformers calls on every forward pass, so on such a machine the app (and the test session) make it answer False.cpython-3.12-windows-aarch64-none), the install options, and the platform's feature differences.The launcher needs a companion change (arch detection, aarch64 uv, native Python request, arm64 package build); it is prepared but not part of this PR.
pins.jsonneeds no change: the launcher's bootstrap path installs from the release's own lockfile.Related Issues / Discussions
NVIDIA RTX Spark Developer Preview: https://forums.developer.nvidia.com/t/rtx-spark-developer-preview/377106
QA Instructions
After merging this repository's
main(Linux, worktree venv):uv lock/uv lock --locked: resolved; againstmain's lock the changes are the ARM64 forks plus bcrypt 3.2.2 → 5.0.0 and passlib removed.check_platform_locks.py uv.lock→linux/aarch64 OK,win32/ARM64 OK(111 packages per ARM64 universe, 144 withtest, none without a wheel);check_pins.py→ consistent.pytest tests/backend/util/test_devices.py tests/app/services/auth tests/app/services/users tests/app/services/shared tests/app/util tests/test_check_pins.py tests/test_check_platform_locks.py tests/backend/util/test_rocm_sdpa_head_dim_guard.py→ 1705 passed, 21 skipped.ruff check/ruff format --checkclean.After the first review round (Linux, worktree venv):
uv lock --locked,check_pins.pyandcheck_platform_locks.pypass; moving the wheel index changes only URLs inuv.lock(identical modulo the repository name).pytest -n 4over the touched areas (image index/map, routers, devices, quantization, patches, model loading, imports, platform locks, wheel publish) → 2043 passed, 153 skipped; the image-map suites again with Windows ARM64 simulated (platform forced, umap/numba hidden) → 346 passed, 1 skipped.Before the move (InvokeAI-7, Linux, worktree venv):
uv lockthenuv lock --locked: resolved; the diff vs main is the ARM64 forks, bcrypt 3.2.2 → 5.0.0, passlib removed, and bitsandbytes 0.49.2 → 0.50.2 for thexpuextra on Linux x86_64 and Windows x64 (verified by parsing both locks: no other package's version or wheel list changed).uv run --no-project --with 'packaging<26' --python 3.12 scripts/check_platform_locks.py uv.lock→linux/aarch64 OK,win32/ARM64 OK(115 packages in each ARM64 universe, none without a wheel).python3 scripts/check_pins.py→ consistent.pytest tests/app/services/auth tests/app/services/image_index tests/app/routers/test_utilities.py tests/backend/image_util tests/test_imports.py tests/test_check_platform_locks.py tests/test_check_pins.py→ pass.pytest -n logical): 8250 passed; 13 failures are the same GPU tests that fail identically on an untouchedmaincheckout because both GPUs on this machine were at 99%/82% use (HIP out-of-memory intest_flux2_working_memory,test_model_cache_*,test_pid_chunked_equivalence), plus the repo-lock check that passes since the lock was regenerated.ruff check/ruff format --checkclean;pnpm -C docs build→ 326 pages, no new warnings.GitHub (InvokeAI-7):
build-win-arm64-wheels: OpenCV, blake3 and tiktoken built and smoke-imported onwindows-11-arm; releasewin-arm64-wheels-v1carries the three wheels andindex.html; the publish job'suv pip compile --find-links <page>verification passed. (First OpenCV attempt failed: MSVC has no__fp16, which the DNN Winograd kernel uses onceNEON_FP16is in the CPU baseline; fixed by pinning the baseline to NEON + DOTPROD dispatch.)py3.12: windows-arm64lane installs from the lock on a native ARM64 interpreter (platform.machine() == "ARM64"asserted), imports the self-built wheels, and runs the full suite: 14,608 passed, 239 skipped, 8 xfailed in 31 minutes (run 39166449058; 37 minutes end to end, against a 60-minute job timeout, with a 600 s per-test timeout). Its runs surfaced these ARM64-only failures, all fixed: the stream-capture crash above (which had taken an xdist worker down and left ~2,500 tests unrun); torch 2.14 rejecting an SDPA test's explicit mask combined withis_causal=True; a frame fixture that overfloweduint8(numpy 2 no longer wraps); a MediaPipe gate test that assumed a non-ARM64 host; a leaked ffmpeg (Chocolatey's ffmpeg is a launcher shim, and cancellation killed only the shim, leaving an endless test source pinning the runner's CPU); and frame counts doubled for clips whose soundtrack outlasts the video (the self-built OpenCV has no FFmpeg backend, and Media Foundation counts frames from the container duration).Not verified (no hardware): CUDA generation on sm_121, cuDNN SDPA priority on this torch build,
cudaMallocAsyncacceptance inconfigure_torch_cuda_allocator(), bitsandbytes 0.50.2's CUDA kernels, VRAM accounting on unified memory. The docs mark the platform as a developer preview.Review
Material findings resolved before the move: the wheel workflow's pull-request trigger could republish non-reproducible wheels over the assets the lock pins by hash (publishing is now dispatch-only under a concurrency group, and wheels are verified before upload); a top-level
import mediapipewould have failedtest_importson ARM64; the woff2 font test needs brotli, absent on ARM64; the checker's closure walk skipped a package's extras once a plain edge had reached it (fixed, with a fixture that fails against the old walk); the MediaPipe error attributed every import failure to the platform; the admin guide still generated password hashes with passlib; bitsandbytes guards catch(ImportError, OSError, RuntimeError)rather than everything; the ARM64 test lane no longer caches uv's store. An old-vs-new lock comparison across the non-ARM64 platforms showed no change beyond bcrypt/passlib.First review round (joshistoast, Pfannkuchensack): the wheel workflow could still replace pinned assets on a dispatch with default inputs, and the wheels lived in an archived repository (both fixed as above); the PCA fallback applied on every platform, was never refit once UMAP became available, and copied the whole matrix to float64; test guards for mediapipe, numba and brotli applied on every platform; one test leaked a cached
Nonefor UMAP into later tests, and the stream-capture shim was installed for the whole Linux test session; the bitsandbytes guards dropped the real error; the aarch64 check stopped requiring per-extra fallback pins and printed lines twice. All fixed with regression tests.After the merge, the ARM64 cryptography pin had nothing left to serve (PyJWT does not need it) and was removed. Second review round (Pfannkuchensack): the lane timeout and the merge with main (fixed as above), plus the projection-method check (now one-way, so a UMAP map survives on a host without umap), the thread hop on every
/pointscall, legacy-hash vectors (>72 bytes,$2a$/$2y$), and test and docs nits. Approval round (Pfannkuchensack): one shared process-tree kill that survives a deniedsuspend(), a deterministic shim test, a WOFF2-unsupported message, bcrypt bounded<6, and Chocolatey's ffmpeg pinned. Remaining risks: GPU behaviour on sm_121 is unverified (see QA), and the ffmpeg probes outsiderun_ffmpeg_process(and main'sencode_rgb_frames, from #9856) still kill only a shim on timeout; they are left for a follow-up.Compatibility / Rollout
<6until a new major is tested. Worth a changelog line.xpuextra now resolvesbitsandbytes0.50.2 on Linux x86_64 and Windows x64, the version thecpu,cudaandrocmextras already use (it was 0.49.2 only forxpu).$2b$12$hashes passlib produced (covered by a regression test), and new hashes use the same cost factor.pyproject.tomltogether, then re-locking; never overwrite a tag that a tagged Invoke release's lock names.nvtorch_ootindex carries a single torch build (2.14.0+cu134); if it is withdrawn, the ARM64 lock breaks until a re-lock.win-arm64-wheelsenvironment so a wheel dispatch cannot publish without approval.Checklist
What's Newcopy (if doing a release after this PR)🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.