deps: duckdb 1.5.5 + pyducklake 1.0.17 — leak-free ducklake channel, drift-gated - #119
Merged
Conversation
…drift-gated The 1.5.2 extension channel is frozen at ducklake build 415a9ebd, which leaks per-connection native memory proportional to catalog metadata churn (A/B-verified in viaduck: ~1MiB per snapshot-advancing bind). The 1.5.5 channel serves d8a1881e, which is flat — millpond's long-lived writer connections against a busy shared catalog have the same exposure. pyducklake (ours) rides along as a deliberate lockstep canary: it hard-pins duckdb, so a one-sided bump of either package fails uv lock instead of silently splitting the two DuckLake stacks. Published yesterday, so it gets a fixed-date exclude-newer-package carve-out from the 7-day cooldown. Because the 1.5.5 channel is LIVE (the frozen channel was accidental drift protection), the Dockerfile now asserts the ducklake build SHA in the extension-install layer — an unexpected ducklake build cannot produce an image at all. Verified both directions: correct SHA builds, wrong SHA fails the layer. The release workflow runs in parallel with CI, so the test canary alone could not stop a drifted build from reaching the fleet via the mutable tag. Behavior changes under d8a1881e, all verified against real catalogs: - The (INT64_MAX, UINT64_MAX] shred-rejection window and its write-time error signature are UNCHANGED; the #118 guard and backstop hold. The inlined-path deferred failure now reports INT128 (was UINT64); the width-agnostic matcher still catches it. - JSON numbers outside [INT64_MIN, UINT64_MAX] in a VARIANT become lossy DOUBLE (were digit-preserving VARCHAR). Deliberate policy: follow native DuckLake semantics; the string column stays authoritative (now asserted). Rows written across the version boundary mix both representations in the companion permanently. - The ducklake attach no longer lists its metadata db as a separate duckdb_databases() row (test-fixture-only impact). - No catalog metadata migration: old and new builds read/write the same catalogs interchangeably, so mixed fleets and co-readers (viaduck, duckgres) are unaffected. New tests/integration/test_ducklake_engine_contract.py pins the engine behaviors the variant guard assumes — the containment invariant (engine-rejected values must be guard-rewritten, probed through the real sanitize_variant_sources chain with the guard bypassed at the engine), its converse (shreddable probes round-trip untouched), boundary values, nested/array/sci-notation shapes, error-signature recognition, and the inlined commit-then-detonate path — so the next bump that shifts any of this fails at the PR instead of on the fleet.
fuziontech
added a commit
that referenced
this pull request
Aug 14, 2026
Keep #119's pyducklake lockstep pin and the 1.5.5-strict VARIANT DOUBLE assertions. Keep the PostHog fork overwrite, and --reinstall the 1.5.5-posthog.2 wheel so uv does not leave the official source_id (d8cdaa33fd) in the image. Runtime stage now asserts both the fork source_id and ducklake SHA d8a1881e.
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.
Why
The 1.5.2 extension channel is frozen at ducklake build
415a9ebd, which leaks per-connection native memory proportional to catalog metadata churn (A/B-verified in viaduck: ~1MiB per snapshot-advancing bind; OOM every 4-6h there). Millpond's long-lived writer connections against a busy shared catalog have the same exposure. The 1.5.5 channel servesd8a1881e, which is flat.pyducklake(ours) rides along as a deliberate lockstep canary — it hard-pins duckdb, so a one-sided bump of either package failsuv lockinstead of silently splitting the two DuckLake stacks. Nothing imports it yet.The drift gate
The frozen 1.5.2 channel was accidental drift protection; 1.5.5's channel is live and can re-serve new builds under the same URL. The release workflow runs in parallel with CI, so the test canary alone can't stop a drifted build from reaching the fleet via the mutable tag + autobounce. The Dockerfile now asserts the ducklake build SHA in the extension-install layer: an unexpected ducklake build cannot produce an image at all. Verified both directions (correct SHA builds;
--build-arg DUCKLAKE_SHA=deadbeeffails the layer with the drift message).Behavior changes under d8a1881e (all verified against real catalogs)
(INT64_MAX, UINT64_MAX]shred-rejection window and write-time error signature are unchanged — the fix: fall back to string-only when the VARIANT write fails #118 guard and backstop hold. The inlined-path deferred failure now reportsINT128(wasUINT64); the width-agnostic matcher still catches it.[INT64_MIN, UINT64_MAX]in a VARIANT become lossyDOUBLE(were digit-preservingVARCHAR). Deliberate policy: follow native DuckLake semantics; the string column stays authoritative (now asserted). Rows written across the version boundary mix both representations in the companion permanently.duckdb_databases()no longer lists the attach's metadata db as its own row — test-fixture-only; no prod code touches it.New engine-behavior contract test
tests/integration/test_ducklake_engine_contract.pypins what the variant guard assumes of the pinned build, probed the way the 2026-08-12 incident executed (guard bypassed, real shredded Parquet writes): the containment invariant (engine-rejected ⊆ guard-rewritten, through the realsanitize_variant_sourceschain), its converse (shreddable probes round-trip untouched), both window boundaries exactly, nested/array/sci-notation shapes, error-signature recognition, and the inlined commit-then-detonate path. The next bump that shifts any of this fails at the PR instead of on the fleet.Supply chain
pyducklake 1.0.17 published 2026-08-13 → fixed-date
exclude-newer-packagecarve-out from the 7-day cooldown (future releases re-enter it until deliberately bumped); sha256-pinned in uv.lock. Added to the dependency-review allow-list (PEP 639-only license metadata, same class as the opentelemetry entries; Apache-2.0).Testing
Authored with agent assistance; two adversarial review passes (correctness + prod-impact/deployment) ran over the diff and their findings are incorporated (drift gate, allow-list entry, lockstep comment, nested/array probes, stale-comment sweep).