diff --git a/PUBLIC_SOURCE_EXPORT.md b/PUBLIC_SOURCE_EXPORT.md index f5df4b4..1cbcaca 100644 --- a/PUBLIC_SOURCE_EXPORT.md +++ b/PUBLIC_SOURCE_EXPORT.md @@ -1,3 +1,3 @@ # Public source export -This source snapshot was generated from the private canonical repository at revision `e92b13f5511700f5410671ee9dd7476efa584d8c`. It contains no private Git history or operational evidence. Changes are published from the canonical repository. +This source snapshot was generated from the private canonical repository at revision `1dd0ededefb2fa3cfdef771106aec0fc54fd87d3`. It contains no private Git history or operational evidence. Changes are published from the canonical repository. diff --git a/PUBLIC_SOURCE_MANIFEST.json b/PUBLIC_SOURCE_MANIFEST.json index 5575a65..156f386 100644 --- a/PUBLIC_SOURCE_MANIFEST.json +++ b/PUBLIC_SOURCE_MANIFEST.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "sourceRevision": "e92b13f5511700f5410671ee9dd7476efa584d8c", + "sourceRevision": "1dd0ededefb2fa3cfdef771106aec0fc54fd87d3", "files": [ { "path": ".dockerignore", @@ -44,8 +44,8 @@ }, { "path": "README.md", - "sha256": "650316a7f7a185bb0100d48e5cf092b4b624d6e3066e54f827f7aab0ee95b481", - "bytes": 4394 + "sha256": "67defbcc1684dfc0010519fe2919a16d9761d18674c9397662b2dfc10706be66", + "bytes": 5045 }, { "path": "SECURITY.md", @@ -984,27 +984,27 @@ }, { "path": "backend/pyproject.toml", - "sha256": "616e61389aaab9d325926558f290959fdff338f60a30ebdb25f24255e77d295e", + "sha256": "7be6d6dd3b81474a4bb50ed8df855d72f136b5d986a49ee64a5fac6ff5495c2f", "bytes": 1156 }, { "path": "backend/requirements-ai-linux.lock", - "sha256": "2361d7748b02f8da4055b54ab5deff5df4a9a5a12aeca9f2736debbf89e3d92d", - "bytes": 5725 + "sha256": "cc5c99f3ae91151707660ac4b912fc299a2cca44bb0c9b4585380f4f9a0e004d", + "bytes": 6275 }, { "path": "backend/requirements-build-tools.lock", - "sha256": "6932e4e0bc14d3226bb33013508522124e205cf57cfb183d989faf4e28611c71", + "sha256": "b951164dbc765a85f7d6aa1dbba0c892de276ea8487f9cd95c4579df54dab7f2", "bytes": 350 }, { "path": "backend/requirements-ci.lock", - "sha256": "e8a908f7c8ce2556d7cb9019e056a292fc41de84c67332cfa31b35feeee7ad36", + "sha256": "64a6fab6a83e0565ba56657d13af9047164aad32ae2df6a517686ba459492238", "bytes": 139649 }, { "path": "backend/requirements-runtime.lock", - "sha256": "c04d6b4b81e3077bc134844b0dfb6ca141c21f8e936e66909c2a937c80541807", + "sha256": "249c769619eddd8369c996a0e148262800d095b23c06801c178a6e3971517637", "bytes": 120817 }, { @@ -1199,7 +1199,7 @@ }, { "path": "backend/tests/test_docker_runtime_config.py", - "sha256": "98eb79664332a3713b0d81bac5ee8fecc1e4036c52d43c2d4592f8704ee3f606", + "sha256": "46fb9b7754de4f5e3595c28671040235cdfd883ee757dc8c7768a6392b1f116a", "bytes": 24147 }, { @@ -1379,7 +1379,7 @@ }, { "path": "backend/tests/test_rc6_supply_chain.py", - "sha256": "7079e746893d7a9ce92cfa0233965d273f9f85ac06064480dc29652ea8181d28", + "sha256": "7f9482fc76315951187e59e70b1b0e5588a85c11ce85cb48666747b9015b5c02", "bytes": 8382 }, { diff --git a/README.md b/README.md index 9a1233e..edbc52b 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,12 @@ docker compose up --build Open . The development stack uses Python 3.11+, Node 20.19+ or 22.12+, and PostgreSQL/PostGIS. Set `GEOINTEL_AUTH_ENABLED=true` and explicitly opt in with `GEOINTEL_GUEST_ACCESS_ENABLED=true` only for a dedicated public-data demo. Guest sessions are short-lived and project-bound; administration and uploads remain restricted. +## Work through an area of interest + +Begin with a small area, select the appropriate source coverage and inspect acquisition dates, coordinate reference systems and quality indicators. Compare the source layers before running an optional model. Review the result against the input evidence, then export the geometry with its provenance. + +Do not treat missing coverage as an empty real-world scene. Building footprints and roof geometry answer different questions, and results from different dates may not be directly comparable. An inference workflow needs the configured model artifacts and supported runtime in addition to a working map interface. + ## Technical overview ```mermaid diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 0353f97..a1bc93d 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -17,7 +17,7 @@ dependencies = [ "pyproj>=3.6.1", "python-multipart>=0.0.9", "itsdangerous>=2.2.0", - "PyJWT[crypto]>=2.14.0", + "PyJWT[crypto]>=2.15.1", "rdflib>=7.1,<8", "alembic>=1.13.2", ] diff --git a/backend/requirements-ai-linux.lock b/backend/requirements-ai-linux.lock index 5a0b0f7..d42c3a8 100644 --- a/backend/requirements-ai-linux.lock +++ b/backend/requirements-ai-linux.lock @@ -1,13 +1,13 @@ # Linux x86_64 / CPython 3.11 AI runtime lock. # -# Resolved on Linux for the production CUDA 12.8 image. Every artifact is +# Resolved on Linux for the production CUDA 12.6 image. Every artifact is # pinned by version and SHA-256 so installation fails closed on index drift. certifi==2026.7.22 --hash=sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 charset-normalizer==3.5.1 --hash=sha256:c7b742bf31c88566b4bb6335a7f393bb322e580b6bb98df7bd0c25e6e3519ce8 contourpy==1.3.3 --hash=sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db cuda-bindings==12.9.7 --hash=sha256:c6496a88d84b1209d6651b0370c19c26319e157c22f6d018bf9a358cd8049041 cuda-pathfinder==1.8.0 --hash=sha256:c44e574dc997fae2814721d1ae97d0fd6db76db82decbe9b753bf75de53f515e -cuda-toolkit==12.8.1 --hash=sha256:adc7906af4ecbf9a352f9dca5734eceb21daec281ccfcf5675e1d2f724fc2cba +cuda-toolkit==12.6.3 --hash=sha256:79d8605baeb6c2f695761e0efb54bc62dbc3c9e32eb0742df7669c07befaa8f7 cycler==0.12.1 --hash=sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30 filelock==3.32.5 --hash=sha256:142cd9fa77a872c5e78c62329a0d15278fadc686eb89e760017968961a4fd6b2 fonttools==4.64.0 --hash=sha256:ff7aff4637fbf71394df139c63ccfe08a47aa4252d2f91224ddb3335c716c925 @@ -20,22 +20,22 @@ matplotlib==3.11.1 --hash=sha256:aee55e9041211bf84302ab55ec3965df18dd90ae19f8b58 mpmath==1.3.0 --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c networkx==3.6.1 --hash=sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762 numpy==2.4.6 --hash=sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93 -nvidia-cublas-cu12==12.8.4.1 --hash=sha256:8ac4e771d5a348c551b2a426eda6193c19aa630236b418086020df5ba9667142 -nvidia-cuda-cupti-cu12==12.8.90 --hash=sha256:ea0cb07ebda26bb9b29ba82cda34849e73c166c18162d3913575b0c9db9a6182 -nvidia-cuda-nvrtc-cu12==12.8.93 --hash=sha256:a7756528852ef889772a84c6cd89d41dfa74667e24cca16bb31f8f061e3e9994 -nvidia-cuda-runtime-cu12==12.8.90 --hash=sha256:adade8dcbd0edf427b7204d480d6066d33902cab2a4707dcfc48a2d0fd44ab90 -nvidia-cudnn-cu12==9.19.0.56 --hash=sha256:ac6ad90a075bb33a94f2b4cf4622eac13dd4dc65cf6dd9c7572a318516a36625 -nvidia-cufft-cu12==11.3.3.83 --hash=sha256:4d2dd21ec0b88cf61b62e6b43564355e5222e4a3fb394cac0db101f2dd0d4f74 -nvidia-cufile-cu12==1.13.1.3 --hash=sha256:1d069003be650e131b21c932ec3d8969c1715379251f8d23a1860554b1cb24fc -nvidia-curand-cu12==10.3.9.90 --hash=sha256:b32331d4f4df5d6eefa0554c565b626c7216f87a06a4f56fab27c3b68a830ec9 -nvidia-cusolver-cu12==11.7.3.90 --hash=sha256:4376c11ad263152bd50ea295c05370360776f8c3427b30991df774f9fb26c450 -nvidia-cusparse-cu12==12.5.8.93 --hash=sha256:1ec05d76bbbd8b61b06a80e1eaf8cf4959c3d4ce8e711b65ebd0443bb0ebb13b +nvidia-cublas-cu12==12.6.4.1 --hash=sha256:08ed2686e9875d01b58e3cb379c6896df8e76c75e0d4a7f7dace3d7b6d9ef8eb +nvidia-cuda-cupti-cu12==12.6.80 --hash=sha256:6768bad6cab4f19e8292125e5f1ac8aa7d1718704012a0e3272a6f61c4bce132 --hash=sha256:a3eff6cdfcc6a4c35db968a06fcadb061cbc7d6dde548609a941ff8701b98b73 +nvidia-cuda-nvrtc-cu12==12.6.85 --hash=sha256:800927308ccc5dd6246d3f61f7fcef2ed7ec4e59e199090d360d3293f78bd5a2 +nvidia-cuda-runtime-cu12==12.6.77 --hash=sha256:a84d15d5e1da416dd4774cb42edf5e954a3e60cc945698dc1d5be02321c44dc8 --hash=sha256:ba3b56a4f896141e25e19ab287cd71e52a6a0f4b29d0d31609f60e3b4d5219b7 +nvidia-cudnn-cu12==9.10.2.21 --hash=sha256:949452be657fa16687d0930933f032835951ef0892b37d2d53824d1a84dc97a8 +nvidia-cufft-cu12==11.3.0.4 --hash=sha256:768160ac89f6f7b459bee747e8d175dbf53619cfe74b2a5636264163138013ca --hash=sha256:ccba62eb9cef5559abd5e0d54ceed2d9934030f51163df018532142a8ec533e5 +nvidia-cufile-cu12==1.11.1.6 --hash=sha256:cc23469d1c7e52ce6c1d55253273d32c565dd22068647f3aa59b3c6b005bf159 +nvidia-curand-cu12==10.3.7.77 --hash=sha256:99f1a32f1ac2bd134897fc7a203f779303261268a65762a623bf30cc9fe79117 --hash=sha256:a42cd1344297f70b9e39a1e4f467a4e1c10f1da54ff7a85c12197f6c652c8bdf +nvidia-cusolver-cu12==11.7.1.2 --hash=sha256:6cf28f17f64107a0c4d7802be5ff5537b2130bfc112f25d5a30df227058ca0e6 --hash=sha256:e9e49843a7707e42022babb9bcfa33c29857a93b88020c4e4434656a655b698c +nvidia-cusparse-cu12==12.5.4.2 --hash=sha256:23749a6571191a215cb74d1cdbff4a86e7b19f1200c071b3fcf844a5bea23a2f --hash=sha256:7556d9eca156e18184b94947ade0fba5bb47d69cec46bf8660fd2c71a4b48b73 nvidia-cusparselt-cu12==0.7.1 --hash=sha256:f1bb701d6b930d5a7cea44c19ceb973311500847f81b634d802b7b539dc55623 nvidia-ml-py==13.610.43 --hash=sha256:f13c72698edef492f985cc225f14faafe68ae065a2e407f45bdf6f4b9b43fde8 -nvidia-nccl-cu12==2.28.9 --hash=sha256:485776daa8447da5da39681af455aa3b2c2586ddcf4af8772495e7c532c7e5ab -nvidia-nvjitlink-cu12==12.8.93 --hash=sha256:81ff63371a7ebd6e6451970684f916be2eab07321b73c9d244dc2b4da7f73b88 +nvidia-nccl-cu12==2.29.3 --hash=sha256:35ad42e7d5d722a83c36a3a478e281c20a5646383deaf1b9ed1a9ab7d61bed53 +nvidia-nvjitlink-cu12==12.6.85 --hash=sha256:eedc36df9e88b682efe4309aa16b5b4e78c2407eac59e8c10a6a47535164369a nvidia-nvshmem-cu12==3.4.5 --hash=sha256:042f2500f24c021db8a06c5eec2539027d57460e1c1a762055a6554f72c369bd -nvidia-nvtx-cu12==12.8.90 --hash=sha256:5b17e2001cc0d751a5bc2c6ec6d26ad95913324a4adb86788c944f8ce9ba441f +nvidia-nvtx-cu12==12.6.77 --hash=sha256:6574241a3ec5fdc9334353ab8c479fe75841dbe8f4532a8fc97ce63503330ba1 --hash=sha256:b90bed3df379fa79afbd21be8e04a0314336b8ae16768b58f2d34cb1d04cd7d2 opencv-python==5.0.0.93 --hash=sha256:c8de2dec111122a02e8beb28e16c31904992dfd6186560b142a92c71403c1039 packaging==26.3 --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c pillow==12.3.0 --hash=sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd @@ -46,14 +46,14 @@ pyparsing==3.3.2 --hash=sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d python-dateutil==2.9.0.post0 --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 pyyaml==6.0.3 --hash=sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d requests==2.34.2 --hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 -setuptools==81.0.0 --hash=sha256:fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6 +setuptools==83.0.0 --hash=sha256:29b23c360f22f414dc7336bb39178cc7bcbf6021ed2733cde173f09dba19abb3 six==1.17.0 --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 sympy==1.14.0 --hash=sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5 -torch==2.11.0+cu128 --hash=sha256:c9a7ca4c74fae10a58e6175b4b2cea953f9322bb6562bbf339ad6a05f52190ad -torchvision==0.26.0+cu128 --hash=sha256:8f2629d056570c929b0a1d5473d9cb0320b90bda1764bda353553a72cc6b2069 -triton==3.6.0 --hash=sha256:e021e87e8f266c6f87bf379b669c43c2800aac6247bdf5d518cb553e3c403c00 +torch==2.13.0+cu126 --hash=sha256:0f4e49e334e24b552f694f6315e0676fb3f816fb0f727871b9c6d1f73784cc25 +torchvision==0.28.0+cu126 --hash=sha256:92f53415dd68e56b6f912441997ab0e78fcd6245b1706ee6e88ce2df917248fa +triton==3.7.1 --hash=sha256:410d3786b2dcf1ef792046670787dc742ba8f800cf2c6dddf56e0656f2260db6 typing-extensions==4.16.0 --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 ultralytics==8.4.99 --hash=sha256:477727b3f07de28f1f34888c7661b7cc3b6bf3e55b9675d7b3eadfa6f4747385 ultralytics-thop==2.1.6 --hash=sha256:23f7b8ad124fa3432c1a7de9279102c4fdda699216032a7dff49f87ec3d1a3af -urllib3==2.7.0 --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 +urllib3==2.8.0 --hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 wheel==0.47.0 --hash=sha256:212281cab4dff978f6cedd499cd893e1f620791ca6ff7107cf270781e587eced diff --git a/backend/requirements-build-tools.lock b/backend/requirements-build-tools.lock index 6372c42..1567634 100644 --- a/backend/requirements-build-tools.lock +++ b/backend/requirements-build-tools.lock @@ -1,4 +1,4 @@ # Build tooling used after the runtime dependency installation. packaging==26.3 --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c -setuptools==81.0.0 --hash=sha256:fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6 +setuptools==83.0.0 --hash=sha256:29b23c360f22f414dc7336bb39178cc7bcbf6021ed2733cde173f09dba19abb3 wheel==0.47.0 --hash=sha256:212281cab4dff978f6cedd499cd893e1f620791ca6ff7107cf270781e587eced diff --git a/backend/requirements-ci.lock b/backend/requirements-ci.lock index 1110f24..418d605 100644 --- a/backend/requirements-ci.lock +++ b/backend/requirements-ci.lock @@ -4,7 +4,7 @@ # # pip-compile --extra=dev --extra=gis --generate-hashes --no-index --output-file=requirements-ci.lock --strip-extras pyproject.toml # -# geointel-input-sha256: 6a94d4ca9742284c1999971e00877b765d987c551b536fd1e15c146a8626f292 +# geointel-input-sha256: afba213a03caac86b67dad23b0c462ff14033151deb1cba2678f9f13e26e4bd0 affine==2.4.0 \ --hash=sha256:8a3df80e2b2378aef598a83c1392efd47967afec4242021a0b06b4c7cbc61a92 \ --hash=sha256:a24d818d6a836c131976d22f8c27b8d3ca32d0af64c1d8d29deb7bafa4da1eea @@ -1095,9 +1095,9 @@ pygments==2.20.0 \ --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via pytest -pyjwt==2.14.0 \ - --hash=sha256:77283c83fb56ecf566a886c757a714bc83668e38156de2cce8263302f42e0b86 \ - --hash=sha256:ad0cef71c756a56e74863c2919cf0985f72decbcfcb550ee2f422e7c62b5eedc +pyjwt==2.15.1 \ + --hash=sha256:42d59d631f7768a1028a64c7ff581a9bf7519804daf91fc5b6c56e30eec5e193 \ + --hash=sha256:4f259e80cdfb6b3fc18a7de51fd1ef9ec79652f25019bae68975ca2468a34df8 # via # geointel-backend (pyproject.toml) # pyjwt diff --git a/backend/requirements-runtime.lock b/backend/requirements-runtime.lock index 6d6631f..26b7169 100644 --- a/backend/requirements-runtime.lock +++ b/backend/requirements-runtime.lock @@ -4,7 +4,7 @@ # # pip-compile --extra=gis --generate-hashes --no-index --output-file=requirements-runtime.lock --strip-extras pyproject.toml # -# geointel-input-sha256: 2e1bf366b76c576b2d17fba2a7841e4442a7480528fe0329a4c784401a4c5c8e +# geointel-input-sha256: 2852682a6398ab7b58adabb99a25e0666a4cc563a5374e5b7f7be895196ac091 affine==2.4.0 \ --hash=sha256:8a3df80e2b2378aef598a83c1392efd47967afec4242021a0b06b4c7cbc61a92 \ --hash=sha256:a24d818d6a836c131976d22f8c27b8d3ca32d0af64c1d8d29deb7bafa4da1eea @@ -880,9 +880,9 @@ pydantic-settings==2.14.2 \ --hash=sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440 \ --hash=sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f # via geointel-backend (pyproject.toml) -pyjwt==2.14.0 \ - --hash=sha256:77283c83fb56ecf566a886c757a714bc83668e38156de2cce8263302f42e0b86 \ - --hash=sha256:ad0cef71c756a56e74863c2919cf0985f72decbcfcb550ee2f422e7c62b5eedc +pyjwt==2.15.1 \ + --hash=sha256:42d59d631f7768a1028a64c7ff581a9bf7519804daf91fc5b6c56e30eec5e193 \ + --hash=sha256:4f259e80cdfb6b3fc18a7de51fd1ef9ec79652f25019bae68975ca2468a34df8 # via # geointel-backend (pyproject.toml) # pyjwt diff --git a/backend/tests/test_docker_runtime_config.py b/backend/tests/test_docker_runtime_config.py index 3be6c50..7cfaf69 100644 --- a/backend/tests/test_docker_runtime_config.py +++ b/backend/tests/test_docker_runtime_config.py @@ -474,11 +474,11 @@ def test_all_in_one_dockerfile_caches_dependencies_and_pins_driver_compatible_cu smoke_index = dockerfile.index("RUN python scripts/gis_import_smoke.py") assert metadata_copy_index < placeholder_readme_index < dependency_install_index < backend_copy_index < smoke_index - assert "GEOINTEL_TORCH_INDEX_URL=https://download.pytorch.org/whl/cu128" in dockerfile + assert "GEOINTEL_TORCH_INDEX_URL=https://download.pytorch.org/whl/cu126" in dockerfile assert '--extra-index-url "$GEOINTEL_TORCH_INDEX_URL"' in dockerfile ai_lock = (ROOT / "backend" / "requirements-ai-linux.lock").read_text(encoding="utf-8") - assert "torch==2.11.0+cu128 --hash=sha256:" in ai_lock - assert "torchvision==0.26.0+cu128 --hash=sha256:" in ai_lock + assert "torch==2.13.0+cu126 --hash=sha256:" in ai_lock + assert "torchvision==0.28.0+cu126 --hash=sha256:" in ai_lock def test_unraid_deploy_passes_ai_build_arg_and_yolo_runtime_env() -> None: @@ -509,4 +509,4 @@ def test_unraid_ai_runtime_requests_nvidia_and_fails_closed() -> None: assert 'YOLO_DEVICE="${YOLO_DEVICE:-cuda:0}"' in run_script assert 'YOLO_REQUIRE_CUDA="${YOLO_REQUIRE_CUDA:-true}"' in run_script assert '-e YOLO_REQUIRE_CUDA="$YOLO_REQUIRE_CUDA"' in run_script - assert "https://download.pytorch.org/whl/cu128" in dockerfile + assert "https://download.pytorch.org/whl/cu126" in dockerfile diff --git a/backend/tests/test_rc6_supply_chain.py b/backend/tests/test_rc6_supply_chain.py index 393ef1b..ce6043e 100644 --- a/backend/tests/test_rc6_supply_chain.py +++ b/backend/tests/test_rc6_supply_chain.py @@ -182,7 +182,7 @@ def test_release_image_uses_locked_non_ai_dependencies_and_npm_ci() -> None: assert "-r requirements-build-tools.lock" in dockerfile assert "--require-hashes" in dockerfile assert "ultralytics==8.4.99 --hash=sha256:" in read("backend/requirements-ai-linux.lock") - assert "torch==2.11.0+cu128 --hash=sha256:" in read("backend/requirements-ai-linux.lock") + assert "torch==2.13.0+cu126 --hash=sha256:" in read("backend/requirements-ai-linux.lock") assert "COPY deploy/unraid/gosu-setpriv /usr/local/bin/gosu" in dockerfile assert "&& pip check" in dockerfile