The coherent set. A release is a declared coherent state across independently versioned artifacts, not a tag and not a green job:
columna 0.18.1
columna-core 0.18.1
columna-server 0.11.1
Wire contract_version stays "4". No field is added, removed or moved.
Two columns were serving a confident wrong number
Both were reproduced under the real runtime before anything was touched, and both are the same shape: a column asserted a population it had not served.
P1-11 — a binary map inherited its alignment domain from the substrate
Planner._apply joined its operands how="inner". That one word is a complete-case participation policy, and nobody declared it: every coordinate the operands did not share was discarded before the absence pass ran, so by the time Φ could have spoken the absence had ceased to exist. The column went on asserting population: <universe> while serving the intersection — the frame naming one population and delivering another.
The alignment domain is now declared. The coordinate is preserved first; only then does law speak. Each operand's own Φ travels into the map, which preserves the one distinction current law can make:
| absent operand | reading | wire |
|---|---|---|
Φ = undefined |
ineligible | out_of_population, immaterial → serve |
Φ = unknown |
eligible but unsupported | data_gap, MATERIAL → disclose |
zero / mixed / none |
undetermined | data_gap, MATERIAL → disclose |
A zero rule never fills a divergence gap. zero declares what an absence of that measure denotes; it says nothing about a coordinate where one operand was present and the other absent, and filling there would assert the expression is nil when what is true is that it is undefined. DATA_GAP was already declared and already wired MATERIAL with zero producers. It now has one.
P1-10 — a family member reduced something its siblings did not
count was registered deliver_sql=lambda p: "count(*)", discarding the operand. So inside a family over a declared VALUE, the siblings reduced the value and count counted rows:
5 rows, 4 observations before after
revenue.count 5 4
avg_obs = revenue.sum / revenue.count 20.0 25.0
lines = AS count(*) 5 5
avg_line = revenue.sum / lines 20.0 20.0
The divergence is removed at its source rather than disclosed, because it had no reason to exist: a family member over a declared VALUE is a reducer over that value. The distinction was already declared and only the delivery threw it away — the parser normalizes the AS-form count(...) to pre_expr = "1" (in that form count means rows), while the VALUE+FAMILY form carries the declared value.
No capability is lost. Row-counting stays fully addressable through AS count(*), and the two readings can be asked side by side and seen to differ. The ambiguity is removed; the choice is not.
P1-12 — recorded, not repaired
Two different measures may both have a row at a coordinate while resting on different underlying support. Neither repair above sees it. The engine delivers one aggregate per measure per coordinate and the observation count is consumed inside the SQL aggregate, so the runtime cannot distinguish a declared divergence from an accidental one. Detecting it needs a companion support carrier on every delivery — new machinery, not a small change — so it is rowed as a bounded blocker in the consolidated ledger and left for Mission C rather than guessed at.
Why columna-server moves — the release-gate sweep, executed
gh pr list --label release-gated --state open returned exactly one PR: #251, the two package front doors. Correct since 14:11 UTC the previous day and blocked only on a bump, because a packaged README is the wheel's long_description and the payload guard rightly refuses a changed payload under a version already on PyPI.
It is taken, not passed over. That is also why the server's version advances at all: its payload changed, so its version advances — the standing rule, not an exception to it.
The server README now types the distinction the package already enforces: the packaged Cascadia demo is hand-authored, carries no SOURCE_MANIFOLD, and is classified ENTRY_LEGACY by admission — it demonstrates serving and the four moods, not the governed path. The governed artifact is firstlight. And this package consumes governed publications rather than producing them.
Governed impact: zero
firstlight's sales_lines has no null amounts, so its served numbers, publication digest, image digest and lowering receipt are byte-identical across the change.
Install
pip install --no-cache-dir "columna==0.18.1" "columna-core==0.18.1" "columna-server==0.11.1"