Changelog#
Each pull request adds its line under ## Upcoming version. A release pull
request renames that heading to the version and the day, such as
## 0.1.0 (2026-10-01), and edits the section into the release notes. Merging
it releases that version (RELEASING.md).
Upcoming version#
- fix(language): a file whose terms read each other's sums is refused at load (#780)
- fix(language): dual(c) is the rate at which the optimal objective rises with the right side of c, so an equality has a sign too (#751)
- fix(language): a macro formal written inside a list takes the name the call binds to it (#779)
- feat(language): a sum names several dimensions in one over= list (#778)
- feat(language): a divisor or a power over parameters may add, so a discount factor is written where it is used (#757)
- docs(language): a reported quotient is absent where its divisor is zero, whether a solve or the data gave that zero (#765)
- fix(language): a given declaration that leaves out its domain or dtype folds into an introducer that sets one (#768)
- fix(advice): an objective that reads a given expression or an empty sum gets advice rather than a KeyError (#767)
- fix(typeset): a term a file adds to a sum keeps its definition line when the expressions are inlined (#766)
- fix(language): merge and override take a list of files, and its order is the order of the terms and of the patches (#761)
- docs: the composition how-to builds a component library from terms each file adds to a sum (#762)
- docs(pypsa): a single spec covers every pypsa model class and component (#620)
- docs(pypsa): the pypsa spec is also 24 topic files that merge back to it, each component adding its share of a sum by name (#736)
- fix(typeset): a substituted term that opens with a minus prints as a subtraction (#759)
- docs: a file restates a shared dimension as its dtype alone, and
mergecarries the one description written for it (#743) - feat(language): a sum other files add terms to is declared as an expression with
empty: true(#742) - docs(notation): the notation page shows a named expression whose declared frame is wider than its body (#756)
- feat(language): a named expression may declare the frame it is read over (#741)
- docs: code examples on the site are readable in light and dark mode, and a diagram shows what mathspec leaves to engines and other tools (#730)
- docs: the site follows the reader's light or dark setting, and a page shows where it sits in the navigation (#727)
- feat(language): a spec is composed from files that each state part of it, and patched with files that each change part of it (#732)
- refactor(language): a term prints as the definition it is, and one rule folds every reading (#738)
- feat(language): two files that state the same spec write one text, and
canonical --checkfails a file that is not in it (#731) - fix(language): a merged spec's descriptions do not depend on the order the fragments are passed in, and a reader's fills one its owner left out (#739)
- docs(pypsa): an efficiency, a rate or a phase shift may change from snapshot to snapshot (#717)
0.2.0 (2026-09-25)#
A file now states a specification, or spec. A model is a spec with data attached, which an engine builds and a solver takes. mathspec holds specs only. The API, the messages and the docs use the two words in these senses (glossary).
This release breaks three things:
- The first parameter of
to_spec,advice,typeset,typeset_declaration,to_latex,to_typstandto_markdownisspec, notmodel. A call that passesmodel=by keyword fails. A positional call works as before. - The module
mathspec.modelis nowmathspec.spec.from mathspec import Specworks as before. - Error and advice messages say "spec" where they said "model". A test that matches the old text fails.
The pull requests in this release:
- feat!: what a file states is called a spec, the functions that read one take it as spec, and model means a spec with data (#721)
- docs: the README and the docs home page say that spec is short for specification (#724)
- fix(docs): the Python API pages link every name a docstring cites, and show advice as the function it is (#720)
0.1.0 (2026-09-25)#
🎉 mathspec is officially on PyPI!
0.1.0rc1 (2026-09-25)#
The release candidate for 0.1.0, the first release on PyPI:
pip install mathspec==0.1.0rc1. The package installs, imports and runs as
mathspec since 0.0.0-alpha.127
(#702). The
0.0.0-alpha.N releases below were tags and GitHub releases only.
- docs: a page says how the package version and the language version of a model file relate (#711)
- docs: the installation page and the PyPI project page say
pip install mathspec, and the README's links resolve on PyPI (#707) - docs: every link to the documentation points at mathspec.readthedocs.io (#706)
0.0.0-alpha.127 (2026-09-25)#
Refactoring#
- the package installs, imports and runs as mathspec, rather than math-spec and math_spec (#702) (f9151af)
0.0.0-alpha.126 (2026-09-25)#
Documentation#
- the site is built by zensical, and its API reference is the public surface rather than every module (#568) (64eb268)
0.0.0-alpha.125 (2026-09-25)#
Bug Fixes#
- language: an unknown operator's refusal points at the limits page instead of an escape key that does not exist (#676) (5e4ef2b)
- language: messages and docs say data is attached rather than bound, so a bound is only a variable's limit (#694) (cc8ba08)
Documentation#
- a development section holds the PyPSA parity pages and the contributing guide (#678) (a399bdd)
- a first tutorial writes the dispatch model one block at a time, checks it and prints it (#680) (48b60e8)
- a glossary defines each word the docs use in a fixed sense (#675) (2561ad8)
- each page keeps only what its reader needs, and a fact stated twice keeps one home (#686) (ef8dcb9)
- engine authors get a program api page rendered from math_spec.program, and the per-module pages and the file-and-program page are gone (#697) (784867a)
- one Python API page documents every public name, including the typesetting functions (#679) (ee5ffdf)
- the nav keeps tutorials, how-to guides, reference and about for model writers, and puts the rest under development (#683) (341ad2a)
- the notation page heads each section with the construct it shows (#682) (66faa7b)
- the readme and home page lead with what a user gets, and name specsolve and linopy as engines (#698) (9fda1bc)
- the readme drops the internals diagram and the repeated formats, and is a third shorter (#699) (234245b)
- what spec.expand() returns is documented on the model writer's python api page, and reading.md keeps only which program an engine reads (#696) (a9caeae)
- what spec.expand() returns is stated once, as a different model that binds the same data (#677) (413550e)
0.0.0-alpha.124 (2026-09-24)#
Features#
- language: a bound is null where it is open, never infinite, in the file and in the program (#689) (8df92d0)
0.0.0-alpha.123 (2026-09-24)#
Documentation#
0.0.0-alpha.122 (2026-09-24)#
Refactoring#
- program: the program no longer exports fan_in, FanIn, quotients or divisor_parameters (#633) (352431b)
0.0.0-alpha.121 (2026-09-24)#
Features#
- language: a model's program is an attribute of the model, and the one door to both states is to_spec (#656) (91f0640)
- language: nothing writes a formulation out unasked (#661) (b5241fd)
Bug Fixes#
- language: a name a curve writes is refused at load whatever declares it, and advice reads a named coefficient's sign (#666) (c1574ab)
Refactoring#
- language: a model loads without writing its curves out, and the program owns the vocabulary the file declares in (#653) (7e93ecb)
- language: every rule that reads across declarations runs in lowering, before any expression is read (#651) (6c1fb6b)
- language: the top-level surface is the two states, the door, the errors, the advice and the typesetter (#660) (5c4f8be)
- program: a program carries the trees the typesetter prints, and every curve is written out before a model becomes one (#649) (762394d)
- program: a program mirrors the file, descriptions and curves included, and the typesetter reads it alone (#650) (bfd628e)
Documentation#
- a page explains why a loaded model is a spec and a program, and which tool reads which (#668) (dc0d731)
0.0.0-alpha.120 (2026-09-23)#
Features#
0.0.0-alpha.119 (2026-09-23)#
Bug Fixes#
- language: a long chain of named expressions loads, a typo beside a formal is refused, and a fault in an entry hides no other (#643) (1e010ca)
- language: a macro template nothing calls is held to every rule a call site is (#628) (ffab0ff)
Refactoring#
- language: an expression resolves straight into the program's own nodes (#638) (b3cee88)
- language: each named expression is resolved once, and every use reads that node (#632) (ceecf69)
- program: a comparison of expressions is one node before and after lowering (#631) (f723602)
0.0.0-alpha.118 (2026-09-23)#
Features#
0.0.0-alpha.117 (2026-09-22)#
Documentation#
- limits: a where cannot test a relation against its target dimension, and composition is a limit on the file (#624) (216208b)
0.0.0-alpha.116 (2026-09-22)#
Features#
- lowering: a program is lowered from the model as it arrived, and a curve left as written is refused (#618) (b15c78a)
0.0.0-alpha.115 (2026-09-22)#
Bug Fixes#
0.0.0-alpha.114 (2026-09-22)#
Documentation#
0.0.0-alpha.113 (2026-09-22)#
Bug Fixes#
0.0.0-alpha.112 (2026-09-22)#
Bug Fixes#
0.0.0-alpha.111 (2026-09-22)#
Features#
- language: a model declares what it assumes of its data (#589) (e1454cf)
- language: a model writes its formulations out on request, and states what each assumes of its data (#602) (1e00c23)
- language: a where counts the coordinates a predicate admits (#592) (5cc55d3)
- language: a where may compare arithmetic over parameters (#566) (e9793bd)
0.0.0-alpha.110 (2026-09-21)#
Documentation#
0.0.0-alpha.109 (2026-09-21)#
Bug Fixes#
0.0.0-alpha.108 (2026-09-20)#
Refactoring#
- program: a program names its nodes by the naming rule and its groups as the file does (#585) (3848821)
0.0.0-alpha.107 (2026-09-20)#
Bug Fixes#
- language: at refuses a read that consumes a column over the dimension it joins on, as sum does (#562) (c10c181)
Refactoring#
- language: a partition is its own class rather than a direction with nothing consumed or produced (#559) (6af0075)
- language: a relation is read in a direction rather than walked (#494) (bbc4344)
0.0.0-alpha.106 (2026-09-19)#
Refactoring#
0.0.0-alpha.105 (2026-09-18)#
Documentation#
0.0.0-alpha.104 (2026-09-18)#
Bug Fixes#
0.0.0-alpha.103 (2026-09-18)#
Documentation#
- the contributing page points at the generated-pages table rather than a stale count (#555) (796ca8a)
0.0.0-alpha.102 (2026-09-18)#
Documentation#
- a rule states what is accepted and stops, rather than naming what it is not (#552) (1019b57)
- every page says what a model author needs and drops rationale, history and internals (#551) (ba6ad9a)
0.0.0-alpha.101 (2026-09-18)#
Documentation#
- language: deciding what a column of data is declared as is a how-to, and the dimensions page keeps the axis (#544) (3540c5c)
- language: named expressions, cases and macros get a page, and the reported page folds into it (#545) (4e49fc7)
- language: relations get a page of their own, and the operators page stops restating how a call reads one (#543) (7e9a572)
- language: the reference pages state their rules and stop arguing for them (#546) (efc9404)
- language: the relations page says what a relation is, how it is spelled, what its data owes, and how it is read, in that order (#549) (6f9e1a4)
- language: the six rules every walk through a relation keeps (#539) (6e93995)
- pinning a variable and writing a curve out by hand are how-tos (#547) (0bf0924)
- reading a loaded model sits beside the Python API rather than among the language pages (#548) (17d1e96)
0.0.0-alpha.100 (2026-09-18)#
Features#
- language: a partition names the value columns it groups by, so a relation may gain one without changing the call (#540) (0da7f50), closes #538
0.0.0-alpha.99 (2026-09-18)#
Features#
- language: a call walks one relation, so by= names one rather than a list (#533) (b78135d)
- language: a relation names the columns its key determines under values: (#504) (d9b0371)
- language: a walk through a relation names both of its ends, and lands only on dimensions it brings (#532) (26f29b0)
0.0.0-alpha.98 (2026-09-18)#
Documentation#
0.0.0-alpha.97 (2026-09-18)#
Features#
- program: a walk that says which regions each node stands under (#482) (3f37cbe), closes #473
- program: every axis names its linking rows and linking columns (#525) (588142f)
Bug Fixes#
0.0.0-alpha.96 (2026-09-17)#
Bug Fixes#
- language: an unknown keyword in an uncalled macro is refused by its signature (#462) (a1659da)
- language: an unknown keyword on an operator is refused once, by its signature (#458) (aa3e052)
0.0.0-alpha.95 (2026-09-16)#
Features#
0.0.0-alpha.94 (2026-09-16)#
Documentation#
- operators: every relational call form prints beside its YAML, the ones that name their columns included (#496) (602c29e)
0.0.0-alpha.93 (2026-09-16)#
Documentation#
- language: a walk through a relation is stated once, in the three verbs the loader uses (#490) (ebc9b16)
0.0.0-alpha.92 (2026-09-16)#
Features#
0.0.0-alpha.91 (2026-09-15)#
Corrected: this release carries no change. #474
was merged and then reverted by #481, both
before the tag was cut, and revert had no section in changelog-sections, so release-please kept
the feature and dropped the revert. The line it published was:
0.0.0-alpha.90 (2026-09-15)#
Documentation#
0.0.0-alpha.89 (2026-09-15)#
Features#
0.0.0-alpha.88 (2026-09-15)#
Documentation#
0.0.0-alpha.87 (2026-09-14)#
Features#
- language: a variable, a constraint and a cased expression declare their shape as dims, as a parameter does (#429) (d8dfdb0)
0.0.0-alpha.86 (2026-09-11)#
Bug Fixes#
0.0.0-alpha.85 (2026-09-10)#
Documentation#
0.0.0-alpha.84 (2026-09-10)#
Bug Fixes#
0.0.0-alpha.83 (2026-09-09)#
Features#
Refactoring#
0.0.0-alpha.82 (2026-09-09)#
Features#
- program: a where predicate's operands are walked with where_children, as an expression's are with children (#416) (b653537)
- typesetting: a backticked name in a description sets in monospace in every format (#421) (a2dcee7)
Bug Fixes#
Performance#
- validation: a model's expressions and where strings are resolved once per load rather than once per reader (#415) (bd86867)
0.0.0-alpha.81 (2026-09-09)#
Documentation#
0.0.0-alpha.80 (2026-09-09)#
Documentation#
0.0.0-alpha.79 (2026-09-09)#
Bug Fixes#
0.0.0-alpha.78 (2026-09-09)#
Bug Fixes#
0.0.0-alpha.77 (2026-09-09)#
Features#
0.0.0-alpha.76 (2026-09-08)#
Bug Fixes#
- program: a parameter under a power is seen by every walk, so a divisor written as a power is named (#404) (1689a7a), closes #403
0.0.0-alpha.75 (2026-09-08)#
Features#
0.0.0-alpha.74 (2026-09-08)#
Features#
- typeset: a named expression prints as a definition, and one declaration prints on its own by name (#385) (f66925e)
0.0.0-alpha.73 (2026-09-02)#
Documentation#
0.0.0-alpha.72 (2026-09-02)#
Features#
- program: a model says whether an axis may be built a window at a time, and what each coordinate needs from its neighbours (#374) (1e029b4)
0.0.0-alpha.71 (2026-09-02)#
Bug Fixes#
0.0.0-alpha.70 (2026-09-02)#
Documentation#
0.0.0-alpha.69 (2026-09-02)#
Bug Fixes#
Refactoring#
- the expression parser is package-private, and the parsed tree is named apart from the program's (#342) (55ff525)
0.0.0-alpha.68 (2026-09-02)#
Documentation#
- language: the rules binding obeys belong to the language, not to whichever engine reads the data (#242) (c05da6a)
0.0.0-alpha.67 (2026-09-02)#
Refactoring#
- a built-in's one positional argument is stated once, and a degree question names the tree it walks (#364) (556af30)
- every rule two passes shared has one home, and a docstring says what a caller needs rather than why (#363) (f24ddd3)
- model: each cross-declaration rule is one method, so a refusal names the rule that raised it (#369) (b25a602)
- piecewise: one block expands itself, holding its names, frame and mask once (#367) (537eadf)
- resolution is one method per node kind, and each operator's dim rule is one function (#368) (c7c2833)
- typesetting: the legend reads what the equations returned rather than state left on the walk (#366) (db96a54)
0.0.0-alpha.66 (2026-09-01)#
Performance#
0.0.0-alpha.65 (2026-09-01)#
Refactoring#
- language: a translation policy and a bound's side name the values they can be, rather than being a string (#354) (d212157)
- typesetting: a format spells the operators the language names, rather than any string a walk happens to ask for (#352) (12b4041)
0.0.0-alpha.64 (2026-09-01)#
Features#
- parser: a refused where string names the rewrite for pandas and C connective habits (#346) (3dbd9b2)
0.0.0-alpha.63 (2026-09-01)#
Refactoring#
- language: an operator, a declaration kind and a notation name the values they can be, rather than being a string (#345) (3f3f858)
0.0.0-alpha.62 (2026-09-01)#
Bug Fixes#
- language: a declaration named what no expression could write is refused, rather than loading unreferenceable (#340) (b865bc1)
0.0.0-alpha.61 (2026-09-01)#
Performance#
0.0.0-alpha.60 (2026-09-01)#
Bug Fixes#
- language: the language reference states which case arms are refused, and the refusal says what actually breaks (#336) (01920d1)
0.0.0-alpha.59 (2026-09-01)#
Bug Fixes#
0.0.0-alpha.58 (2026-09-01)#
Features#
- program: a resolved where is a first-class Mask whose leaves carry their dims, and the where grammar is package-private (#327) (53cc352)
0.0.0-alpha.57 (2026-09-01)#
Bug Fixes#
- program: a program describes a mathematical program rather than being one, and claims neither linearity nor a storage format (#315) (5dfa6be)
0.0.0-alpha.56 (2026-09-01)#
Features#
- program: the conjuncts of a where mask are the program's to give, not each consumer's to re-derive (#313) (db63d3c)
0.0.0-alpha.55 (2026-08-31)#
Documentation#
- ceiling: load-time unit checking has its own refusal, where the data-prep row used to answer for it (#272) (8dfd17d)
0.0.0-alpha.54 (2026-08-31)#
Documentation#
- drop the effects row from the PyPSA-1.3.0 parity table, a feature that release does not have (#305) (92e5ed8)
0.0.0-alpha.53 (2026-08-31)#
Documentation#
- a link's delivery lags its flow, wrapping or losing what is in transit at the horizon's edge (#300) (1d4f10f)
0.0.0-alpha.52 (2026-08-31)#
Documentation#
- examples: the PyPSA file states a constraint once where PyPSA builds one row set, rather than a block per regime (#257) (#292) (c35e637)
0.0.0-alpha.51 (2026-08-31)#
Features#
- a named expression may give a value per region, and no two regions may claim one coordinate (#168) (e12e7da)
0.0.0-alpha.50 (2026-08-31)#
Documentation#
0.0.0-alpha.49 (2026-08-31)#
Features#
Bug Fixes#
- examples: a committable modular unit that is not extendable gets the rows PyPSA builds for it (#271) (5af0ac8)
0.0.0-alpha.48 (2026-08-31)#
Features#
- language: which dims a mask reads is the language's answer, so two consumers cannot restrict one model differently (#269) (350b1ed)
0.0.0-alpha.47 (2026-08-28)#
Documentation#
0.0.0-alpha.46 (2026-08-28)#
Features#
- program: a piecewise assumption names the data it is about, and a derived parameter says how it is filled (#237) (48431b1)
0.0.0-alpha.45 (2026-08-28)#
Bug Fixes#
- language: a negative edge fill prints, the sign of a literal amount being folded once at resolution (#234) (d9303db)
0.0.0-alpha.44 (2026-08-28)#
Bug Fixes#
- language: a where mask is folded at resolution, so a typeset page and a program agree about it (#232) (553bda0)
0.0.0-alpha.43 (2026-08-28)#
Features#
- program: a parameter says which piecewise block derived it, and a label space keeps its dtype (#227) (515dbd5)
- program: a piecewise block is kept as facts — its breakpoints, its mask, and what it assumes of the data (#228) (2fdbd6f)
0.0.0-alpha.42 (2026-08-28)#
Bug Fixes#
- language: a negative sum_back width is refused at load rather than asserting in lowering (#223) (62e52eb), closes #222
0.0.0-alpha.41 (2026-08-28)#
Bug Fixes#
- language: a boolean literal in a where is decided at load wherever it stands (#216) (fab308f), closes #214
0.0.0-alpha.40 (2026-08-28)#
Refactoring#
- program: the declaration vocabularies have one home, so a program cannot spell one differently from the file (#219) (f7596d7), closes #209
0.0.0-alpha.39 (2026-08-28)#
Bug Fixes#
- advice: a model handed over as a program is advised of everything a file is (#217) (4fc50e6), closes #210
0.0.0-alpha.38 (2026-08-28)#
Features#
Bug Fixes#
- a file the language accepts is one every consumer can build, the edge rules being decided at load (#211) (a362ff0)
- program: a where mask cannot be rewritten under another consumer (#197) (ce406b0)
- program: an unknown dimension is refused rather than answered empty (#199) (96fdccf)
- program: every expression node answers fan_in (#202) (f5cc67d)
Refactoring#
- program: a program is built by keyword, so a new field cannot reorder an old call (#203) (214394a)
- program: a program's declarations are keyed by the name the file wrote (#205) (579264a)
- program: drop the two pieces of the program API nothing reaches (#204) (ca25fa5)
- program: expressions are the ones a row is built from, and the declared ones say so (#206) (81aaddd)
- program: the program module says what it promises, rather than offering its whole namespace (#208) (08d2f64)
0.0.0-alpha.37 (2026-08-28)#
Features#
- a model is checked from the shell, advice included, with no consumer installed (#192) (941126c)
- advice carries which pass said it and which declaration it is about, so a consumer can filter rather than parse (#195) (89408f6)
Refactoring#
0.0.0-alpha.36 (2026-08-28)#
Refactoring#
- a program is trusted by construction, so the language's rules are checked once, on the spec (#189) (45931b1)
0.0.0-alpha.35 (2026-08-28)#
Documentation#
0.0.0-alpha.34 (2026-08-28)#
Refactoring#
- two public states and a conversion to each, where the surface was seventy-seven names (#180) (718e2de)
0.0.0-alpha.33 (2026-08-28)#
Features#
- the notes a check prints are reachable, so a consumer surfaces them rather than re-deriving them (#184) (19ef814)
0.0.0-alpha.32 (2026-08-28)#
Features#
0.0.0-alpha.31 (2026-08-28)#
Documentation#
0.0.0-alpha.30 (2026-08-28)#
Documentation#
0.0.0-alpha.29 (2026-08-27)#
Features#
- language: dimension members and lookup maps come from the data, rather than from the file (#169) (f3c4e5f)
0.0.0-alpha.28 (2026-08-27)#
Bug Fixes#
0.0.0-alpha.27 (2026-08-27)#
Bug Fixes#
- the linearized rung states its three caps as rows and starts one unit cold, so every block it declares is built (#162) (cb4863f)
0.0.0-alpha.26 (2026-08-27)#
Features#
0.0.0-alpha.25 (2026-08-27)#
Features#
- rung 11 — PyPSA's ac-dc-meshed example, whole (#151) (a133044)
- rung 12 — linearized unit commitment, a file of its own (#152) (69b926e)
- rung 13 — transmission losses in tangent form, a file of its own (#153) (379ce23)
- rung 14 — two-stage stochastic with CVaR, a file of its own (#154) (41b427d)
- rung 15 — investment periods with a growth limit, a file of its own (#155) (285aac3)
0.0.0-alpha.24 (2026-08-26)#
Features#
- PyPSA in one file — every rung stated, shown beside its data, and solved to the same objective on both lanes (#122) (46544e3)
0.0.0-alpha.23 (2026-08-26)#
Bug Fixes#
- docs: the homepage feature cards render as cards rather than as loose rules and paragraphs (#145) (b88e5dc)
0.0.0-alpha.22 (2026-08-26)#
Features#
0.0.0-alpha.21 (2026-08-26)#
Documentation#
0.0.0-alpha.20 (2026-08-26)#
Documentation#
0.0.0-alpha.19 (2026-08-26)#
Bug Fixes#
0.0.0-alpha.18 (2026-08-26)#
Refactoring#
- parser: one number rule, one amount table, and a namespace nothing builds by hand (#106) (f775a07)
- schema: one wording for an undeclared dimension, and the front door validates once (#105) (69e42db)
- the stack's own additions say less and repeat nothing (#102) (119e588)
- typeset: Markdown is LaTeX's math with its own document layer, and a step merges itself (#107) (1ca9178)
0.0.0-alpha.17 (2026-08-25)#
Bug Fixes#
- language: a link takes any affine expression, an uncalled template hides no typo, and degree is decided at load (#91) (a653056)
- parser: a negation is over a power, a keyword is given once, and an amount is a number or a name (#88) (4bf994c)
- schema: every refusal of a malformed file is a SchemaError, and an empty declared map survives a round trip (#89) (ee07736)
- schema: two literal bounds that cross are refused at load (#97) (30589ba)
- typeset: a sum under its own dimension takes a fresh index, and prose escapes its markup (#92) (20c7076)
Refactoring#
0.0.0-alpha.16 (2026-08-25)#
Refactoring#
0.0.0-alpha.15 (2026-08-25)#
Documentation#
0.0.0-alpha.14 (2026-08-25)#
Documentation#
0.0.0-alpha.13 (2026-08-25)#
Bug Fixes#
0.0.0-alpha.12 (2026-08-25)#
Documentation#
0.0.0-alpha.11 (2026-08-25)#
Bug Fixes#
- enforce the two rules a named offset or width was always said to obey (#61) (5bd92dc), closes #58
- let sum_back stop at each group's edge, as its checks already assumed (#65) (cb58e88)
- refuse a negated named amount, and one read where there is no coordinate (#63) (15d9c25), closes #62
0.0.0-alpha.10 (2026-08-24)#
Features#
Refactoring#
- name the groups a pass asks about, and spell each operator once (#52) (e35c46c)
- the package is
typesetting, the function staystypeset(#54) (a1d9599)