Acknowledge the Colab oracle drift, and stop the diff hiding entries (#11324)

* Acknowledge the Colab oracle drift, and stop the diff hiding entries

Notebooks CI has been red since at least 2026-09-16 on

    A rule-bearing Colab oracle drifted from its committed snapshot; run
    `notebook_validator.py refresh-colab --all --snapshot-dir scripts/data`
    to acknowledge.

That is the tripwire working: any drift in pip-freeze.gpu.txt is strict by
construction, because the rules resolve a notebook's installs against it. What
it wants is an acknowledged refresh, so this is one, with the diff read rather
than waved through.

What moved: 91 pip entries (3 new, 1 removed, 87 changed), notably
transformers 5.15.0 -> 5.16.1 and datasets 4.0.0 -> 4.8.5; the base image from
Ubuntu 22.04.5 to 24.04.1; 1261 apt entries. torch did not move, and neither
did the Python line, which is why only the pip oracle tripped --strict.

The evidence that acknowledging is safe: linting all 445 notebooks in
unslothai/notebooks against the old and the new oracle gives the same 82
findings, 0 new and 0 resolved. This is upstream churn no rule resolves
differently, not a compatibility change being papered over.

Robustification, from a defect this drift exposed. colab-diff caps its lists at
50/50/80 and elides the rest with a bare count, and transformers 5.15.0 ->
5.16.1 sat past the CHANGED cap -- reading the output, that package looked
untouched. Every entry in the pip oracle is rule-bearing, so an elided one is
exactly what a reviewer may be deciding on. Added --full, and the elision now
names it instead of leaving it to be guessed at. Two tests cover both halves;
removing the flag's effect fails both. tests/notebooks: 314 passed, 2 skipped.

Not addressed here: the nine "smoke install (Colab-shaped venv, opt-in)" jobs
in the same workflow also failed. Their logs have expired, so I have not
diagnosed them and this change does not claim to fix them.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Daniel Han 2026-09-19 00:04:01 -07:00 • committed by GitHub
parent ba0887a292
commit 6f8df52cbc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 1256 additions and 1181 deletions

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@
# Be aware that this list does not necessarily reflect the current state of the
# staging or production container, but rather the state as of the most recent
# submitted CL where extract_colabx_testing_tarballs.sh was run.
Ubuntu 22.04.5 LTS
Ubuntu 24.04.1 LTS
Python 3.13.15
R version 4.6.1 (2026-06-24) -- "Happy Hop"
julia version 1.12.6

View file

@ -6,7 +6,7 @@
absl-py==1.4.0
accelerate==1.14.0
access==1.1.10.post3
affine==3.0.0
affine==3.0.1
aiofiles==25.1.0
aiohappyeyeballs==2.7.1
aiohttp==3.14.3
@ -24,31 +24,31 @@ anyio==4.14.2
anywidget==0.9.21
apsw==3.53.4.0
argon2-cffi==25.1.0
argon2-cffi-bindings==25.1.0
argon2-cffi-bindings==26.1.0
array_record==0.8.3
arrow==1.4.0
arviz==0.22.0
astropy==7.2.2
astropy-iers-data==0.2026.8.10.0.32.39
astropy-iers-data==0.2026.8.31.0.57.9
astunparse==1.6.3
atpublic==5.1
attrs==26.1.0
audioop-lts==0.2.2
audioread==3.1.0
Authlib==1.7.2
Authlib==1.8.0
autograd==1.9.1
babel==2.18.0
backcall==0.2.0
beartype==0.22.9
beautifulsoup4==4.13.5
betterproto==2.0.0b7
bigframes==2.42.0
bigframes==2.48.0
bigquery-magics==0.14.0
bleach==6.4.0
blinker==1.9.0
blis==1.3.3
blobfile==3.2.0
blosc2==4.11.0
blobfile==3.3.0
blosc2==4.12.0
bokeh==3.8.2
Bottleneck==1.4.2
bqplot==0.12.47
@ -62,9 +62,9 @@ cffi==2.1.1
chardet==5.2.0
charset-normalizer==3.4.9
clarabel==0.11.1
click==8.4.2
click==8.5.0
cligj==0.7.2
cloudpathlib==0.24.0
cloudpathlib==0.25.0
cloudpickle==3.1.2
cmake==3.31.10
cmdstanpy==1.3.0
@ -74,12 +74,12 @@ community==1.0.0b1
confection==1.3.3
cons==0.4.7
contourpy==1.3.3
cramjam==2.11.0
cryptography==50.0.0
cramjam==2.12.1
cryptography==50.0.1
cucim-cu12 @ https://pypi.nvidia.com/cucim-cu12/cucim_cu12-26.2.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
cuda-bindings==12.9.7
cuda-core==0.3.2
cuda-pathfinder==1.6.0
cuda-pathfinder==1.8.0
cuda-python==12.9.7
cuda-toolkit==12.8.1
cudf-cu12==26.2.1
@ -87,7 +87,7 @@ cudf-polars-cu12==26.2.1
cufflinks==0.17.3
cuml-cu12==26.2.0
cupy-cuda12x==14.0.1
curl_cffi==0.16.0
curl_cffi==0.16.2
cuvs-cu12 @ https://pypi.nvidia.com/cuvs-cu12/cuvs_cu12-26.2.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
cvxopt==1.3.2
cvxpy==1.6.7
@ -99,15 +99,15 @@ dask==2026.1.1
dask-cuda==26.2.0
dask-cudf-cu12==26.2.1
dataproc-spark-connect==1.1.0
datasets==4.0.0
datasets==4.8.5
db-dtypes==1.7.1
dbus-python==1.2.18
dbus-python==1.3.2
debugpy==1.8.15
decorator==4.4.2
defusedxml==0.7.1
deprecation==2.1.0
diffusers==0.39.0
dill==0.3.8
diffusers==0.40.0
dill==0.4.1
distributed==2026.1.1
distributed-ucxx-cu12==0.48.0
distro==1.9.0
@ -131,28 +131,29 @@ etuples==0.3.10
Farama-Notifications==0.0.6
fastai==2.8.8
fastapi==0.141.1
fastcore==2.2.12
fastcore==2.2.19
fastdownload==0.0.7
fastjsonschema==2.22.2
fastprogress==1.1.6
fasttransform==0.0.2
filelock==3.32.3
filelock==3.32.5
firebase-admin==6.9.0
Flask==3.1.3
flatbuffers==25.12.19
flax==0.11.2
folium==0.20.0
fonttools==4.63.0
fonttools==4.64.0
formulaic==1.2.2
fqdn==1.5.1
frozendict==2.4.7
frozenlist==1.8.0
fsspec==2025.3.0
fsspec==2025.12.0
future==1.0.0
gast==0.7.0
gcsfs==2025.3.0
gcsfs==2025.12.0
GDAL==3.8.4
gdown==5.2.2
geemap==0.38.3
geemap==0.38.4
geocoder==1.38.1
geographiclib==2.1
geopandas==1.1.4
@ -164,14 +165,14 @@ google==3.0.0
google-adk==2.7.1
google-ai-generativelanguage==0.6.15
google-api-core==2.30.3
google-api-python-client==2.198.0
google-api-python-client==2.200.0
google-auth==2.49.0
google-auth-httplib2==0.4.1
google-auth-oauthlib==1.4.0
google-cloud-bigquery==3.43.0
google-auth-httplib2==0.4.2
google-auth-oauthlib==1.4.1
google-cloud-bigquery==3.44.0
google-cloud-bigquery-connection==1.22.0
google-cloud-bigquery-storage==2.39.0
google-cloud-core==2.6.1
google-cloud-core==2.7.0
google-cloud-dataproc==5.28.0
google-cloud-datastore==2.25.0
google-cloud-firestore==2.27.0
@ -181,24 +182,25 @@ google-cloud-monitoring==2.31.0
google-cloud-resource-manager==1.18.0
google-cloud-spanner==3.68.0
google-cloud-storage==3.13.1
google-cloud-storage-control==1.12.0
google-cloud-translate==3.27.0
google-colab @ file:///colabtools/dist/google_colab-1.0.0.tar.gz
google-crc32c==1.8.0
google-genai==2.12.1
google-generativeai==0.8.6
google-pasta==0.2.0
google-resumable-media==2.10.1
google-resumable-media==2.10.2
googleapis-common-protos==1.75.0
googledrivedownloader==1.1.0
gradio==6.24.0
gradio_client==2.6.0
gradio==6.26.0
gradio_client==2.6.1
grain==0.2.18
graphviz==0.21
greenlet==3.5.5
groovy==0.1.2
grpc-google-iam-v1==0.14.4
grpc-interceptor==0.15.4
grpcio==1.83.0
grpcio==1.83.1
grpcio-status==1.71.2
grpclib==0.4.9
gspread==6.2.1
@ -215,34 +217,35 @@ hf-gradio==0.4.1
hf-xet==1.6.0
highspy==1.15.1
holidays==0.103
holoviews==1.23.1
holoviews==1.23.2
hpack==4.2.0
html5lib==1.1
httpcore==1.0.9
httpcore2==2.10.0
httpcore2==2.12.0
httpimport==1.4.1
httplib2==0.32.0
httptools==0.8.0
httpx==0.28.1
httpx2==2.10.0
huggingface_hub==1.27.0
httpx2==2.12.0
huggingface_hub==1.29.0
humanize==4.16.0
hyperframe==6.1.0
hyperopt==0.3.0
ibis-framework==9.5.0
idna==3.18
idna==3.19
ImageIO==2.37.4
imageio-ffmpeg==0.6.0
imagesize==2.0.0
imagesize==2.0.1
imbalanced-learn==0.14.2
immutabledict==4.3.1
importlib_metadata==9.0.0
importlib_metadata==9.0.1
imutils==0.5.4
inequality==1.1.2
inflect==7.5.0
iniconfig==2.3.0
intel-cmplr-lib-ur==2025.3.3
intel-openmp==2025.3.3
interface_meta==2.0.1
ipyevents==2.0.4
ipyfilechooser==0.6.0
ipykernel==6.17.1
@ -257,16 +260,16 @@ itsdangerous==2.2.0
jaraco.classes==3.4.0
jaraco.context==6.1.2
jaraco.functools==4.6.0
jax==0.7.2
jax-cuda12-pjrt==0.7.2
jax-cuda12-plugin==0.7.2
jaxlib==0.7.2
jax==0.11.1
jax-cuda12-pjrt==0.11.1
jax-cuda12-plugin==0.11.1
jaxlib==0.11.1
jeepney==0.9.0
jieba==0.42.1
Jinja2==3.1.6
jiter==0.16.0
joblib==1.5.3
joserfc==1.7.4
joblib==1.6.0
joserfc==1.7.5
jsonpatch==1.33
jsonpickle==4.1.2
jsonpointer==3.1.1
@ -281,7 +284,7 @@ jupyter_kernel_gateway @ git+https://github.com/googlecolab/kernel_gateway@b134e
jupyter_server==2.20.0
jupyter_server_terminals==0.5.4
jupyterlab_pygments==0.3.0
jupyterlab_widgets==3.0.16
jupyterlab_widgets==3.0.17
jupytext==1.19.5
kaggle==2.0.2
kagglehub==1.0.2
@ -291,18 +294,18 @@ keras-hub==0.26.0
keras-nlp==0.26.0
keyring==25.7.0
keyrings.google-artifactregistry-auth==1.1.2
kiwisolver==1.5.0
langchain==1.3.15
langchain-core==1.5.5
langchain-protocol==0.0.18
kiwisolver==1.5.1
langchain==1.3.18
langchain-core==1.6.1
langchain-protocol==0.0.19
langgraph==1.2.11
langgraph-checkpoint==4.2.0
langgraph-prebuilt==1.1.0
langgraph-sdk==0.4.2
langsmith==0.11.0
langgraph-sdk==0.4.4
langsmith==0.12.1
lark==1.3.1
launchpadlib==1.10.16
lazr.restfulclient==0.14.4
launchpadlib==1.11.0
lazr.restfulclient==0.14.6
lazr.uri==1.0.6
lazy-loader==0.5
libclang==18.1.1
@ -318,12 +321,12 @@ librosa==0.11.0
libucx-cu12==1.19.0
libucxx-cu12==0.48.0
lightgbm==4.6.0
linkify-it-py==2.1.0
linkify-it-py==2.2.0
llvmlite==0.44.0
locket==1.0.0
logical-unification==0.4.7
lxml==6.1.1
Mako==1.1.3
lxml==6.1.2
Mako==1.3.2.dev0
mapclassify==2.10.0
Markdown==3.10.3
markdown-it-py==4.2.0
@ -341,20 +344,20 @@ mizani==0.13.5
mkl==2025.3.1
ml_dtypes==0.6.0
mlxtend==0.23.4
mmh3==5.2.1
mmh3==5.3.0
momepy==0.11.0
more-itertools==10.8.0
moviepy==1.0.3
mpmath==1.3.0
msgpack==1.2.1
msgpack==1.2.2
multidict==6.7.1
multipledispatch==1.0.0
multiprocess==0.70.16
multiprocess==0.70.19
multitasking==0.0.13
murmurhash==1.0.15
music21==9.9.2
namex==0.1.0
narwhals==2.24.0
narwhals==2.25.0
natsort==8.4.0
nbclassic==1.3.3
nbclient==0.10.4
@ -363,7 +366,7 @@ nbformat==5.11.1
ndindex==1.10.1
nest-asyncio==1.6.0
networkx==3.6.1
nh3==0.3.6
nh3==0.3.7
nibabel==5.4.2
nltk==3.9.1
notebook==6.5.7
@ -410,7 +413,7 @@ opentelemetry-sdk==1.42.1
opentelemetry-semantic-conventions==0.63b1
opt_einsum==3.4.0
optax==0.2.8
optree==0.19.1
optree==0.20.0
orbax-checkpoint==0.12.4
orjson==3.12.0
ormsgpack==1.12.2
@ -427,14 +430,14 @@ param==2.4.1
parso==0.8.7
parsy==2.2
partd==1.4.2
patsy==1.0.2
peewee==4.3.0
patsy==1.0.3
peewee==4.4.0
peft==0.20.0
pexpect==4.9.0
pickleshare==0.7.5
pillow==11.3.0
pip==24.1.2
platformdirs==4.11.3
platformdirs==4.11.7
plotly==5.24.1
plotnine==0.14.5
pluggy==1.6.0
@ -462,15 +465,15 @@ ptyprocess==0.7.0
PuLP==3.3.2
py-cpuinfo==9.0.0
py4j==0.10.9.9
pyarrow==18.1.0
pyarrow==23.0.1
pyasn1==0.6.4
pyasn1_modules==0.4.2
pycairo==1.29.1
pycocotools==2.0.11
pycparser==3.0
pycryptodomex==3.23.0
pydantic==2.13.4
pydantic_core==2.46.4
pydantic==2.13.5
pydantic_core==2.46.5
pydata-google-auth==1.9.1
pydot==4.0.1
pydotplus==2.0.2
@ -481,7 +484,7 @@ pygame==2.6.1
pygit2==1.20.0
Pygments==2.21.0
PyGObject==3.48.2
pyiceberg==0.11.1
pyiceberg==0.12.0
PyJWT==2.13.0
pylibcudf-cu12==26.2.1
pylibcugraph-cu12==26.2.0
@ -506,13 +509,13 @@ python-apt==0.0.0
python-box==7.4.1
python-dateutil==2.9.0.post0
python-dotenv==1.2.3
python-fasthtml==0.14.11
python-fasthtml==0.14.12
python-json-logger==4.2.0
python-louvain==0.16
python-multipart==0.0.32
python-slugify==8.0.4
python-snappy==0.7.3
python-utils==4.0.0
python-utils==4.0.1
pytz==2025.2
pyviz_comms==3.0.6
PyWavelets==1.9.0
@ -556,13 +559,13 @@ semantic-version==2.10.0
Send2Trash==2.1.0
sentence-transformers==5.7.0
sentencepiece==0.2.2
sentry-sdk==2.68.0
setuptools==75.2.0
sentry-sdk==2.68.1
setuptools==80.10.2
shap==0.52.0
shapely==2.1.2
shellingham==1.5.4
simple-parsing==0.1.9
simplejson==4.1.1
simplejson==4.1.2
simsimd==6.5.16
six==1.17.0
sklearn-compat==0.1.6
@ -575,7 +578,7 @@ sortedcontainers==2.4.0
soundfile==0.14.0
soupsieve==2.9.2
soxr==1.1.0
spacy==3.8.15
spacy==3.8.16
spacy-legacy==3.0.12
spacy-loggers==1.0.5
spaghetti==1.7.6
@ -601,7 +604,7 @@ standard-chunk==3.13.0
standard-sunau==3.13.0
stanio==0.5.1
starlette==1.6.0
statsmodels==0.14.6
statsmodels==0.15.0
strictyaml==1.7.3
stringzilla==5.1.2
stumpy==1.14.1
@ -629,12 +632,12 @@ tf-slim==1.1.0
tf_keras==2.20.1
thinc==8.3.13
threadpoolctl==3.6.0
tifffile==2026.8.16
tifffile==2026.8.23
tiktoken==0.14.0
timm==1.0.28
timm==1.0.29
tinycss2==1.5.1
tobler==0.14.0
tokenizers==0.22.2
tokenizers==0.23.1
toml==0.10.2
tomlkit==0.14.0
toolz==0.12.1
@ -650,22 +653,21 @@ tornado==6.5.7
tqdm==4.67.3
traitlets==5.7.1
traittypes==0.2.3
transformers==5.15.0
treelite==4.7.0
transformers==5.16.1
treelite==4.7.1
treescope==0.1.10
triton==3.6.0
truststore==0.10.4
tsfresh==0.21.2
tweepy==4.17.0
typeguard==4.6.0
typer==0.27.1
typer==0.27.2
types-pytz==2026.3.1.20260727
types-setuptools==84.0.0.20260812
typing-inspection==0.4.4
typing_extensions==4.16.0
tzdata==2026.3
tzlocal==5.4.4
uc-micro-py==2.0.0
ucxx-cu12==0.48.0
umap-learn==0.5.12
umf==1.0.3
@ -673,7 +675,7 @@ uri-template==1.3.0
uritemplate==4.2.0
urllib3==2.5.0
uuid_utils==0.17.0
uvicorn==0.52.3
uvicorn==0.52.4
uvloop==0.22.1
vega-datasets==0.9.0
wadllib==1.3.6
@ -681,17 +683,17 @@ wandb==0.28.1
wasabi==1.1.3
watchdog==6.0.0
watchfiles==1.2.0
wcwidth==0.8.2
wcwidth==0.8.3
weasel==1.0.0
webcolors==25.10.0
webencodings==0.6.1
websocket-client==1.9.0
websocket-client==1.9.2
websockets==15.0.1
Werkzeug==3.1.8
wheel==0.48.0
widgetsnbextension==3.6.10
wordcloud==1.9.6
wrapt==2.3.0
wrapt==2.4.0
xarray==2025.12.0
xarray-einstats==0.11.0
xgboost==3.4.1

View file

@ -3835,18 +3835,30 @@ def cmd_colab_diff(args: argparse.Namespace) -> int:
elif drifted_strict_keys:
strict_diff = True
print(f" (rule-bearing key drifted: {', '.join(drifted_strict_keys)})")
for k, v in new[:50]:
# Every package in the pip oracle is rule-bearing -- the rules resolve a notebook's
# installs against it -- so the caps below hide entries a reviewer may be looking for.
# transformers 5.15.0 -> 5.16.1 sat past the CHANGED cap in the drift that prompted
# --full, reading as though it had not moved at all. Name the flag in the elision so
# the output says how to see the rest instead of leaving it to be guessed at.
cap_new = len(new) if args.full else 50
cap_removed = len(removed) if args.full else 50
cap_changed = len(changed) if args.full else 80
for k, v in new[:cap_new]:
print(f" NEW {k}=={v}")
if len(new) > 50:
print(f" ...and {len(new) - 50} more new entries")
for k, v in removed[:50]:
if len(new) > cap_new:
print(f" ...and {len(new) - cap_new} more new entries (--full to list them)")
for k, v in removed[:cap_removed]:
print(f" REMOVED {k} (was {v})")
if len(removed) > 50:
print(f" ...and {len(removed) - 50} more removed entries")
for k, old, ver in changed[:80]:
if len(removed) > cap_removed:
print(
f" ...and {len(removed) - cap_removed} more removed entries (--full to list them)"
)
for k, old, ver in changed[:cap_changed]:
print(f" CHANGED {k}: {old} -> {ver}")
if len(changed) > 80:
print(f" ...and {len(changed) - 80} more changed entries")
if len(changed) > cap_changed:
print(
f" ...and {len(changed) - cap_changed} more changed entries (--full to list them)"
)
if strict_diff and args.strict:
print(
"\n::error::A rule-bearing Colab oracle drifted from its committed "
@ -3922,6 +3934,11 @@ def main(argv: list[str] | None = None) -> int:
action = "store_true",
help = f"exit 1 on {COLAB_STRICT_ORACLE} drift (default: advisory; exit 0)",
)
pa.add_argument(
"--full",
action = "store_true",
help = "print every drifted entry instead of capping each list",
)
args = p.parse_args(argv)
return {

View file

@ -69,8 +69,14 @@ def oracle(tmp_path, monkeypatch):
return upstream, tmp_path
def _diff(snapshot_dir, strict):
return nv.cmd_colab_diff(argparse.Namespace(snapshot_dir = str(snapshot_dir), strict = strict))
def _diff(
snapshot_dir,
strict,
full = False,
):
return nv.cmd_colab_diff(
argparse.Namespace(snapshot_dir = str(snapshot_dir), strict = strict, full = full)
)
def test_no_drift_is_clean(oracle):
@ -111,6 +117,34 @@ def test_non_rule_oracles_never_fail_strict(oracle, capsys, name, drifted):
assert "::notice::" in out
def test_a_capped_listing_says_how_to_see_the_rest(oracle, capsys):
"""Every package in the pip oracle is rule-bearing, so an entry the cap elides is one a
reviewer may be deciding on. In the drift this was written for, transformers 5.15.0 ->
5.16.1 sat past the CHANGED cap and the output read as though it had not moved at all.
"""
upstream, snapshot_dir = oracle
upstream["pip-freeze.gpu.txt"] = "".join(f"pkg{i}=={i}.0\n" for i in range(200)) + PIP
assert _diff(snapshot_dir, strict = False) == 0
capped = capsys.readouterr().out
assert "more new entries (--full to list them)" in capped, capped
assert capped.count(" NEW ") == 50, capped
def test_full_lists_every_drifted_entry(oracle, capsys):
upstream, snapshot_dir = oracle
upstream["pip-freeze.gpu.txt"] = "".join(f"pkg{i}=={i}.0\n" for i in range(200)) + PIP
assert _diff(snapshot_dir, strict = False, full = True) == 0
full = capsys.readouterr().out
assert "more new entries" not in full, full
assert full.count(" NEW ") == 200, full
# The entry the cap would have hidden, by name rather than by count.
assert "NEW pkg199==199.0" in full, full
def test_strict_oracle_is_the_one_lint_pins_against(oracle):
"""--colab-pin is fed COLAB_FALLBACK_FILE, and that is the snapshot whose
drift is fatal. If these ever diverge the tripwire is guarding the wrong