Conversation
A file declares the columns and row families it reads and does not build under one closed key, given: variables: and given: constraints:. A given name is in the namespace every expression resolves against, has a frame for the dimension check, and dual() may name a given row family. The file typesets on its own, with a Given legend group. The program carries the declarations under Program.given, lowering does not refuse, and advice gains the kind given, one note per declaration a consumer binds. A dimension only a given declaration indexes counts as reached. The schema is regenerated; the golden output does not move.
…ne, and given: sits beside variables: A given name asked of typeset_declaration was refused with "is not a named expression, constraint or variable". It now says that a given declaration prints no line of its own, and that it prints in the legend under Given. The `given` field moves after `variables` on Spec, so to_yaml writes the key where the file-shape table and the examples already put it. The schema and the golden output are unchanged. The symbols kwarg `given` is renamed to `upright`: it means the glyph, not the language's `given:` key. `balnce`, the did-you-mean input in tests/test_given.py, joins the typos allowance.
override(base, patches) lays each patch over the base a field at a time and hands back one mapping for to_spec. A partial entry must land on a declaration the base has, and a miss is refused with the near miss named. A whole entry creates. null at declaration level removes, and a stale removal is refused. Sibling patches must write disjoint paths, so their order never decides a model. A dimension or a relation may be added or restated exactly and never changed. The objective is one declaration laid over by the same rules. given: is laid over one kind at a time, entry by entry. Base and patches are copied, never mutated. override is exported from math_spec. The tests' own fixture override is renamed varied so the verb owns the word. docs/howto/compose.md carries the recipe and the four refusals, each produced by running the case.
…nd a null section is refused
`override` read `dimensions: {snapshot: null}` as a removal and `dimensions:
{snapshot: {}}` as a restatement, though the rule is that a patch adds a
dimension or a relation or restates one word for word. Both are refused now,
with a message that names the rewrite.
A section set to null, such as `constraints: null`, laid as an empty mapping
and changed nothing. It is refused too, and the message says that removal is
written one declaration at a time.
The page and the messages now say dimension and relation throughout, where
they said axis in some places and dimension in others.
… sibling introduces merge(fragments, description=None) composes peers before validation. A dimension or a relation every fragment may declare, and the ones that do say the same thing about it, prose excluded. Every other name is owned, and a second claim is refused naming both fragments. The objectives are summed, each term in parentheses, and the senses and the versions have to agree. A given declaration is folded into the declaration a sibling introduces, once the reader is checked to say the same or less, and two fragments that both only read a name have to read it the same way. merge is exported beside override, the given advice names merge() as the fragment's route, and compose.md, declarations.md and limits.md describe both verbs.
…annot read what it builds The composed objective joined its terms in fragment-iteration order, so the same fragments under two argument orders gave two expressions. The terms are summed in the fragments' name order now. A fragment that declares a name and reads it under given: too is refused, naming the fragment, the name and the rewrite. Such a file does not load on its own, and folding the reading away put it in a model that loads. merge writes version: only where a fragment declares one. Two fragments declaring different versions are still refused.
… file prints alone examples/library/ holds a coupling surface, a generator and a load as fragments, and variants/commitment.yaml as a patch over their composition. One symbol table serves the library, cut per page to what each model declares. tools/gallery.py prints a page per fragment and a composed page with one tab per variant; tab() moves to tools/_page.py; render_tex skips variants/. tests/test_library_example.py holds the library to what its pages claim. Sentence lengths on the five pages: median 8 to 15 words, three sentences over 25.
…t flow one way The layout rules keep the rule sentence and drop the clause that argued for it. The library pages say "surface" where one said "spine", and the component fragments call `Port_p` a flow, as the surface and its page already do. The composed page's variant test reads the page and asks for a tab per file under `variants/`, rather than comparing a glob with itself. The balance test compares each merge against the surface's own row, which is what the page claims. The gallery picks the library block by the model's directory.
The two verbs typed their inputs and results as dict[str, Any], which the type gate on main refuses. They now take a Mapping[str, object] like every other entry point, and read a section through one helper that names the shape the closed schema checks at load. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012aGN1gzy2vbqGchcQ8TbfV
FBumann
added this pull request to stack #693
September 24, 2026 20:50
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8Y8AoPsJCyMsURHvgzm7h
…sumer binding it "Bind" collided with a variable's bounds, which the glossary keeps as the only sense of "bound". The glossary gains a Provide entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8Y8AoPsJCyMsURHvgzm7h
Contributor
Author
Note The following content was generated by AI. Superseded by #732. Generated by Claude Code |
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.
This replaces #571. It holds the same nine commits, with Fabian as author, rebased onto
main41 commits later, plus one commit that satisfiesmain's type gate. #571's description still holds for the design. This body lists only what the rebase changed.What this changes
What #571 changes: a closed
given:key,math_spec.merge,math_spec.override, and the component library underexamples/library/. The rebase ported that ontomain's refactors:mainmoved them intovalidation.py(chore(language): the rules one declaration is held to against the others are checked before any expression is read #651). The threegivenrules now live there: a given variable joins the flat namespace, given frames join the dimension check, and a row family cannot be both built and given. The given variable also joins the name check for what a curve or set writes out.legend.py, andGivenDeclarationcarries adescriptionso the legend can print it. The refusal for a given name asked oftypeset_declarationstays intypesetting/__init__.py, becausewalk.pyis held to golden coverage.to_programis gone (feat(language): a model's program is an attribute of the model, and the one door to both states is to_spec #656). The tests andreading.mdreadto_spec(…).program.mainhad already addedassumptions:as the eleventh, so withgiven:a file has twelve declaration keys. feat(language): a file says what it reads, and fragments and patches compose into one model #571 said eleven.file.md,index.mdand theSpecdocstring now say twelve.Anyis refused onmain. The last commit typesmergeandoverrideas takingMapping[str, object], liketo_spec.mergeandoverridestay exported frommath_specand pinned intest_public_surface.py, although refactor(language): the top-level surface is the two states, the door, the errors, the advice and the typesetter #660 narrowed that surface. Whether they belong in amath_spec.compositionmodule is open.Why
#571 could not merge:
mainrefactored the modules it touches. This is the rebase, so the linopy work can build ongiven:against currentmain.Gates, what was not run, what follows
Gates run on the final tree:
pixi run lintpasses.pixi run test: 1752 passed.mkdocs buildshows no warnings except one: this sandbox cannot fetch thedocs.python.orginventory, which fails--strict.render-texrendered 34 models.Not run.
compile-tex: the tectonic bundle download is blocked in this sandbox.balncetypo that commit 2 allows.Stacked on this. #690 (merge and override load every model they compose,
nullin a patch makes what it names absent, and a merged model keeps its assumptions). #689 onmainis related (an open bound isnull).Not done.
Program.givendrops thedomaina file states.givenis not empty.Generated by Claude Code