Repository navigation
v0.17.0 — materialized measure state served the wrong population
columna 0.17.0 · columna-core 0.17.0 · columna-server 0.11.0
Two defects in the sketch/witness path were serving a confident wrong number. Both were reproduced under the real runtime before they were touched, and both now carry standing tests verified to fail against the pre-fix source.
Fixed
A carved universe was not carved in materialized state. _build_base_sketches delivered base rows and never confined them — no _confine, no grain augmentation for the levels the universe predicate reads, and the where it forwarded was the query WHERE rather than the universe predicate. A distinct count over a restricted universe therefore served the unconfined population, while its own disclosure asserted [over <universe>]: the frame claimed the confined population and delivered the other one. In the shipped reproduction the engine returned 3 where the declared carve admits 1.
On the same universe a sum confined correctly, so one Manifold answered two different populations depending on the operator. Both the eager published witness and the lazy fallback build were wrong identically — one shared defect, not a materialization bug.
Confinement now happens on the raw rows, before hll_count, because an HLL sketch cannot be filtered afterwards: an out-of-universe value that reaches the carrier is in it permanently.
Unknown data identity was fail-OPEN on the witness store. WitnessStore.fresh compared None == None and reported a stale witness as current. A real data mutation stayed invisible — 2 served against a ground truth of 3, at zero backend fetches, with no staleness disclosure. The result cache, built on the same identity primitive, was fail-CLOSED throughout: one primitive, two opposite polarities.
fresh() now refuses an unknown or unversioned identity, and put() refuses to store an unversioned witness at all. Unknown identity closes storage, not merely reuse — a witness stored without a version can never be shown stale, so storing one converts a missing identity into a permanent claim of freshness.
Witness currency now uses the complete computation dependency set. It was data_version(home_table) while the result cache on the same request used data_version_of(computation_tables(...)), so a change to a universe-predicate provider re-derived the monoid answer and left the witness "fresh".
These three shipped together deliberately. The currency defect was latent only because the confinement defect existed — the witness never read the predicate, so its content genuinely depended on the home table alone. Fixing confinement alone would have converted a cancelled defect into an active staleness bug.
Changed — user-visible strings
Four refusal and clarification strings reachable at runtime named a commercial tier that does not exist. Each was reclassified individually; there was no global replacement.
| surface | was | now |
|---|---|---|
| fan-out clarify | WITH allocation — … [Pro] |
[ROADMAP — not available in this build] |
| windowed-scan refusal | windowed scans are Pro in this build |
not implemented in this build [ROADMAP] |
| scan alternative | windowed scans (rolling_*) [Pro] |
… [ROADMAP] |
| unknown operator | (Core registry: …); custom operators are Pro |
(registry: …); custom operators are [ROADMAP] |
The operator registry is the shared extension point, not a Core/Pro seam. Custom operators are ROADMAP — unbuilt, not withheld. Consumers matching on these strings should read the wire code and materiality fields instead; the codes did not change.
Also
The columna-core README is repaired: it no longer heads itself 0.7.8-core (nine minor versions stale, in the heading PyPI renders), no longer describes capabilities as "deliberately out (Pro)", and no longer documents a FAMILY { <agg> [: <tier>] } clause that the parser rejects with bad FAMILY member.
Why minor and not patch: served values change, reuse semantics change, and four user-visible strings change.
columna-server stays at 0.11.0 — its floor is satisfied and none of its own source moved.