Conversation
…the direction each call names `over:` lists the columns, `key:` is the claim that makes the table a map, and `from=`/`to=` on the call say which column an operator consumes and which it produces; the other key columns are joined on. A one-key, one-value table still reads `sum(p, by=gen_bus)` and `at(x, by=gen_bus)` unchanged. Without a key the table is a bare relation: `sum` walks it with both ends named, a bare `where` tests it, and `at`, `shift` and `position` refuse it. Two columns over one dimension are named by role, which is how a self-map is declared. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FD5LpGRzAWdi5sKWXDdnHC
…oduct or is read at two columns at once Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FD5LpGRzAWdi5sKWXDdnHC
…the row, and the golden model renders it Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FD5LpGRzAWdi5sKWXDdnHC
…ion walks the one key column over its dimension Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FD5LpGRzAWdi5sKWXDdnHC
…so one calendar table serves every granularity Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FD5LpGRzAWdi5sKWXDdnHC
…a key nor a column name claims a dimension it is not over A partition lands nothing, so its group columns are not checked as dimensions the call produces. A key names one column per dimension, since a frame carries each once. A column named like a dimension is over that dimension. GroupSum and At hold their walks alone and read over, coordinate and into off them; a Walk holds its LookupDeclaration, which is the one home of a lookup's roles, values and column dims. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FD5LpGRzAWdi5sKWXDdnHC
…and each cardinality names its declaration The lookups reference says what `key:` means in uniqueness terms, that a composite key leaves each column non-unique on its own, and which declaration says many-to-one, one-to-many and many-to-many. One-to-one is named as a claim the language does not have. Page measure after the change (docs-writing script): 78 sentences, median 25 words, 38 over 25; the two new paragraphs add sentences of 7 to 25 words. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016LDbfiWuoU2U8g8vV6iWq5
…ator lost in preparation is not read as one on no bus `coverage: total | masked` on a keyed lookup, default `total`: every key tuple has a row, over the product of the key columns' dimensions, and the consumer that binds the table refuses one short of a key. `masked` says the gap is meant. A bare relation has no key to be total over and declaring `coverage:` on it is refused at load, as is the bare `where: name` on a `total` lookup, where every key has a row and the mask selects nothing. The program carries it on `LookupDeclaration.coverage`, `None` for a bare relation. `coverage` is not typeset, the precedent `dtype` sets. Coverage moved: the golden model's `zone_of`, the dimension tests' `gen_bus` and `gen_zone`, and the lowering test's `zone_of` declare `masked`, since each tests the bare where form. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016LDbfiWuoU2U8g8vV6iWq5
Documentation build overview
24 files changed ·
|
FBumann
added this pull request to stack #439
September 9, 2026 20:40
FBumann
removed this pull request from stack #439
September 10, 2026 06:46
FBumann
added this pull request to stack #448
September 10, 2026 06:46
FBumann
force-pushed
the
claude/lookup-relations-vhvfjd
branch
from
September 10, 2026 08:50
2546a8a to
75840fd
Compare
FBumann
removed this pull request from stack #448
September 11, 2026 09:51
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.
Note
The following content was generated by AI. Stacked on #437; the base branch is its head. The lookup half of #245, restated for a relation with a key. The parameter half stays in #245.
What this changes
A keyed lookup takes
coverage: total | masked, defaulttotal: every key tuple has a row, and the consumer that binds the table refuses one short of a key.maskedsays the gap is meant. A bare relation declares neither, and a barewhere:on atotallookup is refused, since it masks nothing.Per key, not per column or per value. The key is the one column set where "every tuple of the product has a row" is the claim anyone wants: it is the parameter rule one axis over, so
totalmeans the same on both blocks. Per column is weaker on a composite key, and per value column ("every period has a snapshot") is a claim about the other dimension's labels rather than about the table.Two refusals, both decided by the file alone.
The second follows the precedent of a bare dimension name in a
where, which is refused for the same reason. It is the one decision here that could be dropped without touching the rest; say so and it goes.What consumers see.
LookupDeclaration.coverageisCoverage | None:totalormaskedfor a keyed table,Nonefor a bare relation, which answers for no coverage the way #245's block-owned parameters do.Namespacecarries it too, since the where refusal reads it.coverageis not typeset, the precedentdtypesets, and the golden.outfiles are byte-identical.Coverage moved. Four fixtures test the bare
where: nameform on a keyed lookup and now declaremasked: the golden model'szone_of, the dimension tests'gen_busandgen_zone, and the lowering test'szone_of. No example inexamples/uses a bare lookup name in awhere, so none changed.Every guard deleted in turn
Each on a clean tree at 31a6595, restored with
git checkout --and__pycache__dropped on both sides; the tree came back clean and the suite at 1211 passed.maskedtotalinstead ofNoneVerified
uv venv on Python 3.13 with
ruff==0.16.1andpyrefly==1.2.0; pixi is blocked here. On 31a6595 over the #437 head:pytest -q -n auto1211 passed, 6 skipped (the two TeX compilers).ruff check,ruff format --check,reuse lint,prettier --list-differenton every docs page: clean.mkdocs build --strictpasses with the python.org inventory removed, which the proxy answers 403. Every generator re-run (tools.schema,tests.typesetting.golden,tools.notation,tools.gallery,tools.spec_math,tools.home_math); the schema andnotation.mdmoved, nothing else. The two messages quoted above are the loader's own output on a model built to trigger them.Not run:
compile-tex;pixi run ciitself.pyrefly checkreports 11 errors in this venv, the same 11 on the base branch (unused ignores and noyamlstubs), so they are the environment's.typosflagstypin five places, none of them in a file this PR touches.Why
key:says at most one row per key tuple, never at least one. A snapshot with no period, a generator on no bus, are rows lost in preparation, and today the language reads each as "belongs to no group" and drops its terms from every sum silently. That is the data-safety hole cardinality does not close; totality does, and the two compose: a key plustotalis a total function.Stacked on #437 because that PR changes what "total" is over: a composite key is total over the product of its dimensions, and a bare relation has nothing to be total over, which is the refusal above.
🤖 Generated with Claude Code
https://claude.ai/code/session_016LDbfiWuoU2U8g8vV6iWq5
Generated by Claude Code
Superseeds #438 #430 #256