Repository navigation
refactor(language): a relation is read in a direction rather than walked - #494
Merged
Merged
Conversation
Documentation build overview
48 files changed ·
|
Contributor
Author
|
@brynpickering Please approve this merge. |
FBumann
force-pushed
the
claude/busy-volta-1z98iq
branch
2 times, most recently
from
September 16, 2026 17:29
5d80d4c to
24af4e9
Compare
`program.Walk` becomes `program.Direction`, and the field both nodes hold becomes `direction`. `_Resolver._walk` and `_partition_walk` become `_direction` and `_partition_direction`, and nine refusals say what a call does to a relation instead of describing a traversal. A `Direction` is one relation and one join — which columns are consumed, which produced, which joined on. It is never a sequence and carries no accumulator, so "walk" promised a fold that is not there. The language now says so itself: since #533 one call reads one relation, so there is not even a list to compose. The word stays where the thing is a traversal: `program.walk`, `walk_regions`, `_expression_parser.nodes`, and the typesetter's own `Walk`, which is a fold with `_Context` as its accumulator. That module imported `Walk as RelationWalk` to hold both meanings at once; it imports `Direction` now and the alias is gone. The axis sense stays too — `shift`, `sum_back` and `position` step along an ordered dimension. The refusals that changed, in full: ...names 2 relations, and one call reads one table ...this sum lands on the key ['g'], so each coordinate has one term A call names both of its ends, so that a relation may gain a value column... A relation is read between two of its columns and joined at the others... A call brings the dims it lands on, so that reading it tells you what it adds ...and a partition steps along a key column over the dimension it groups `dimensions.md` renames its `### Walks` section to `### Directions`, and the two links into it follow. This renames an exported name: `math_spec.program.Walk` no longer exists and `Direction` is in `program.__all__` in its place. lpspec reads the old name and needs a follow-up once this tags; it pins math-spec by tag, so nothing breaks before then. pytest: 1294 passed, 6 skipped. ruff check, ruff format, typos, prettier and `mkdocs build --strict` clean — the strict build is what proves the renamed anchor has no dead link left. pyrefly reports the 3 pre-existing missing `yaml` stubs. The five generators were re-run: only `notation.md` moved, and only where it quotes the golden model's comments. The golden `.out` files did not move, so the typeset math is unchanged. `pixi` cannot be installed in this environment, so the gates ran from a pip environment on Python 3.13; `compile-tex` is CI's to run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NUhbXWGiyZF46wHp3fVnr2
FBumann
force-pushed
the
claude/busy-volta-1z98iq
branch
from
September 18, 2026 12:19
24af4e9 to
6bcc68b
Compare
FBumann
pushed a commit
that referenced
this pull request
Sep 18, 2026
`dimensions.md` states the frame law and the four invariants the notation is held to, above the bullets that were already its consequences. Two of the five were on the page (the key is fixed, a call brings the dims it lands on) and stay in their bullets, which carry the worked example each needs; three were nowhere. The law is the one the loader computes, checked against it line by line: `_sum_dims` and `_at_dims` both return `(operand − consumed) ∪ produced`, `_check_joined` holds the operand to `consumed ∪ joined`, and `_check_lands_clear` refuses on `(produced ∩ operand) − consumed`. The joined set is `key − (consumed ∪ produced)`, which is symmetric: for `sum` it reduces to `key − consumed`, for `at` to `key − produced`. The block says "a call" throughout rather than "a walk", so it reads the same whichever way #494 goes. Sentence length on the page: n 117, avg 16.8, median 17, 13 over 25 — against n 105, avg 17.0, median 17, 13 over 25 before, so the block adds no long sentence. `mkdocs build --strict` clean, `tests/test_docs.py` 33 passed, prettier and typos clean. The page is not generated, so no generator was involved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NUhbXWGiyZF46wHp3fVnr2
The rename lands on the docs and the partition rules that #539–#552 and #540 rewrote. The relations page main added already says "direction", so the sweep now only reaches the four operator-page sentences, the dimension-set table's error column and the declare-a-column how-to that still said "walk". `_partition_direction` takes the `within=` columns main made required, and `Direction`'s docstring says the group is the ones `within=` named. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016mvLvAhLGB26wJ4gsCtRSe
…st that still walked a relation The relation docstring that the schema prints, the Direction class's own docstring, three node docstrings, three example descriptions and the test names and ids all said "walk" for a relation. They say "read" now. The axis sense was half renamed: four places said "steps along" and six still said "walks". It is "steps along" everywhere, which reaches the typesetter's position note and so the golden outputs and the generated pages. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UnbTmmYp7auaiCwSgkKKsB
FBumann
added this pull request to stack #560
September 18, 2026 20:09
The one conflict is the sum-to-key refusal, which #558 corrected on main while this branch renamed it: the assertion keeps this branch's "lands on the key" and #558's full at(..., by=lk, over=['h'], into=['g']) rewrite, which the merged source emits. The rename sweep reaches the test #558 added, whose name and docstring called the read a walk. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V2SFmoxEF3SnaPKp7HbZTk
FBumann
removed this pull request from stack #560
September 19, 2026 18:10
FBumann
added this pull request to stack #574
September 19, 2026 18:10
FBumann
removed this pull request from stack #574
September 19, 2026 18:12
FBumann
added this pull request to stack #575
September 19, 2026 18:12
Conflict in dimensions.py: #529 dropped RelationNode.shown in favour of __str__, this branch renamed "walks" to "reads" on the same line. Both. #529 also added a test that builds program.Walk, which this branch renamed to Direction. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DUyQztqnwapp3vHPhzBLw5
FBumann
pushed a commit
that referenced
this pull request
Sep 20, 2026
Carries origin/main up the stack of #494. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DUyQztqnwapp3vHPhzBLw5
FBumann
pushed a commit
that referenced
this pull request
Sep 20, 2026
Carries origin/main up the stack of #494. #529 gave every expression node a __str__; this branch had split RelationNode into DirectionNode and PartitionNode, so both get one. The dims conflicts are #529's obsolete RelationNode arm against this branch's Direction/Partition refactor, which wins. The node-prints-itself test came from #529 against the two-field RelationDeclaration and the unsplit node; it is rebuilt on both halves. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DUyQztqnwapp3vHPhzBLw5
FBumann
pushed a commit
that referenced
this pull request
Sep 20, 2026
…plit-kdqegz Carries origin/main up the stack of #494. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DUyQztqnwapp3vHPhzBLw5
FBumann
pushed a commit
that referenced
this pull request
Sep 20, 2026
…ession-parser-language-split-kdqegz-arithmetic-where Carries origin/main up the stack of #494. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DUyQztqnwapp3vHPhzBLw5
FBumann
pushed a commit
that referenced
this pull request
Sep 20, 2026
… into claude/mathspec-piecewise-api-7j0wpt Carries origin/main up the stack of #494. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DUyQztqnwapp3vHPhzBLw5
FBumann
pushed a commit
that referenced
this pull request
Sep 20, 2026
Carries origin/main up the stack of #494. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DUyQztqnwapp3vHPhzBLw5
This was referenced Sep 20, 2026
FBumann
removed this pull request from stack #575
September 20, 2026 20:34
FBumann
added this pull request to stack #583
September 20, 2026 20:35
This was referenced Sep 20, 2026
refactor(program): a program names its nodes by the naming rule and its groups as the file does
#585
Merged
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.
What this changes
program.Walkbecomesprogram.Direction, and the fieldGroupSumandAthold becomesdirection._Resolver._walkand_partition_walkbecome_directionand_partition_direction. Nine refusals say what a call does to a relation instead of describing a traversal, and the operators page, the dimension-set table, the declare-a-column how-to, the relation docstring the schema prints, three example descriptions and the tests say the same.The axis sense is renamed too:
shift,sum_backandpositionstep along a dimension, in every refusal, docstring and page, and in the typesetter's position note, which is what moves the golden outputs and the generated example pages.Why
A
Directionis one relation and one join — which columns are consumed, which produced, which joined on. It is never a sequence and carries no accumulator, so "walk" promised a fold that is not there.Since #533 the language says so itself: one call reads one relation, so there is not even a list to compose.
What keeps the word
The traversals that really are traversals:
program.walk,walk_regions,_expression_parser.nodes, and the typesetter's ownWalkclass, which is a fold —_arithmeticcombines each child's text into its parent's and_Contextis the accumulator carried down. That module importedWalk as RelationWalkto hold both meanings at once; it importsDirectionnow and the alias is gone.Stacked on this
#559 takes the partition out of
Direction. A partition consumes and produces nothing, soDirection's docstring here still has to redefine its own fields forshift,sum_backandposition. That paragraph goes with the split.The refusals that changed
Why Direction, and not the alternatives
The tree already used the noun when it had to explain the concept:
model.py("An operator walks the table in the direction the call names … the declaration fixes no direction"),dimensions.py("sum is the direction that produces them") and the relations page ("The declaration fixes no direction. A call names the columns it reads"). Renaming the class to it removes the second vocabulary rather than adding one.The word is not unambiguous in prose.
dimensions.pysays a width "has no direction", meaning the sign of a shift along an axis, and the check and errors pages say "the direction a +slack term improves a minimize objective in". No sentence holds two of the three senses, and neither of the other two is a name in code.Arrowwas dropped on two collisions and one wrong implication: lpspec definesArrowTablefor the Apache Arrow PyCapsule stream in the module that reads relations as tables;typesetting/format.pyalready spellsmaps_toas\to/arrow.r; and an arrow reads as single-valued, which a direction over a bare relation is not.Lookupdescribesatand notsum.Crossingcollides with the cross join in lpspec's compiler, andStepwith_Stepin the typesetter.Readmatches the verb the messages use, but the language already callsat"a read", so aReadthatsumholds too would collide with the kinds table on the relations page.The break
math_spec.program.Walkno longer exists;Directionis inprogram.__all__in its place. lpspec reads the old name and needs a follow-up once this tags — it pins math-spec by tag, so nothing breaks before then.Redone on today's main, not replayed
The branch was three commits on
4069792. Four merges since then — #504, #532, #533 and #535 — rewrote the same code and the same messages, so replaying the old diff would have conflicted on nearly every hunk and, worse, left the "walk" prose those PRs added untouched. A rename is a sweep, and the sweep has to cover the tree as it is now. The branch is reset tomainand the sweep redone there, as one commit.Two things the old branch planned no longer exist.
GroupSum.walksandAt.walksarewalksingular since #533, so they becomedirectionrather thandirections. The docs commit that corrected a sentence aboutby=lists is moot: the list form went out with #533.Merged with main, and what the docs rewrite moved
mainwas merged in at0d93f01. Six files conflicted:program.py,resolution.py,operators.pyand three language pages.The source conflicts are all #540, which made
within=required and took the partition's group from the columns it names._partition_directionnow takeswithin_roles: tuple[str, ...]rather than an optional one, andDirection's docstring says the group is the columnswithin=named.The docs conflicts are the #543–#552 rewrite, which took the relations material out of
dimensions.mdinto a page of its own. That page states the rule this PR argues for — "The declaration fixes no direction. A call names the columns it reads" — so the### Walks→### Directionsrename this PR planned has nothing left to rename. What the sweep reaches instead is the prose those merges wrote: four sentences on the operators page, the error column of the dimension-set table inexpressions.md, and two rows ofdocs/howto/declare-a-column.md.The second sweep
A review of the first sweep found "walk" for a relation in the relation docstring the schema prints, in
Direction's own docstring, in three node docstrings, in three example descriptions, and in the names, ids and messages of the tests. It also found the axis sense half renamed: four places said "steps along" and six still said "walks". Commit6526f76reaches all of them, and regenerates the schema, the goldens and the generated pages.Rebased onto main at
bda1fc5Merged, not replayed: the hard rule here is never to force-push, and this
branch already carried two
mainmerges.mainbrought #573, #576 and #529,and was carried up all six branches stacked above this one.
One conflict, in
dimensions.py. #529 droppedRelationNode.shownfor__str__on the same line this branch changed "walks" to "reads". Theresolution takes both:
f'sum(by={by}) consumes {missing}, the dims it reads from,'.#529 also added
test_a_node_resolution_built_prints_the_name_the_file_wrote,which constructs
program.Walk— renamed toDirectionhere. That fileauto-merged without a conflict and did not compile, so a clean merge was not
a passing build at any level of this stack.
Gates
pixi.shis refused by this environment's egress proxy, so the gates ran froma
uvenvironment on Python 3.12, which is a departure from the "everythingruns in a pixi environment" default. Re-run on the rebased head; the counts
below replace the pre-rebase ones.
pytest -n autoruff check,ruff formatpyrefly checktypos,reuse lintprettiermkdocs build --strictdocs.python.orginventory dropped for the run — the proxy refuses it with a 403compile-texThe schema, the goldens and the generated pages were re-run and did not move.
The 6 skips are a missing
typst, not failures. CI ran the whole gate on thishead,
compile-texincluded, and was green.🤖 Generated with Claude Code
https://claude.ai/code/session_01DUyQztqnwapp3vHPhzBLw5
Generated by Claude Code