Skip to content

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 merge carries 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 --check fails 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_typst and to_markdown is spec, not model. A call that passes model= by keyword fails. A positional call works as before.
  • The module mathspec.model is now mathspec.spec. from mathspec import Spec works 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!

pip install mathspec

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#

  • the engine these pages point at is called specsolve (#673) (647e351)

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#

  • language: a sos block says along, not over, for the dimension its set runs along (#646) (57062de)

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#

  • language: a where may read a predicate through a relation with at() (#634) (6190cf4)

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#

  • typeset: a set prints under the name its sos: block declares (#615) (f2c91e8)

0.0.0-alpha.114 (2026-09-22)#

Documentation#

  • expand: every formulation expands to a hand-written file the suite compares whole (#611) (d7069b2)

0.0.0-alpha.113 (2026-09-22)#

Bug Fixes#

  • language: a gap in points: is explained by the rows its method writes (#612) (e903272)

0.0.0-alpha.112 (2026-09-22)#

Bug Fixes#

  • language: an expanded curve declares only the parameters the file declared (#609) (423468e)

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#

  • language: the relations page states what decides a sum from a read (#597) (3f6b632)

0.0.0-alpha.109 (2026-09-21)#

Bug Fixes#

  • language: a read that lands outside the key is refused (#598) (ce6359c)

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#

  • no signature says Any, and a symbol table section that is not a mapping is refused (#572) (394599b)

0.0.0-alpha.105 (2026-09-18)#

Documentation#

  • the README's folded document renders as math rather than as TeX (#563) (8c1d9ba)

0.0.0-alpha.104 (2026-09-18)#

Bug Fixes#

  • language: a sum refused for walking to the key names an at() the language accepts (#558) (352fc7e)

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#

  • program: linking rows and columns say when they are the whole border (#527) (7972ad0)

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#

  • typesetting: a grouped sum's domain carries every column its walk fixes (#513) (cd78ca5)

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#

  • language: a relation declares key columns and value columns (#501) (4069792)

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#

  • program: a grouped sum and a pullback say which dimensions their walks join on (#488) (dd05088)

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:

  • program: a walk that says which regions each node stands under (#474) (3986c6b)

0.0.0-alpha.90 (2026-09-15)#

Documentation#

  • the README shows the math a model prints, in all three formats (#449) (aad56d9)

0.0.0-alpha.89 (2026-09-15)#

Features#

  • language: a relation between dimensions, walked in the direction each call names (#437) (3284926)

0.0.0-alpha.88 (2026-09-15)#

Documentation#

  • limits: a whole-table operator is priced at a barrier rather than refused (#468) (835e4a4)

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#

  • language: a where that mistypes a lookup name lists the lookups (#455) (46c48b2)

0.0.0-alpha.85 (2026-09-10)#

Documentation#

  • the pages read in plain English, arranged by what each is for (#442) (8dc4b60)

0.0.0-alpha.84 (2026-09-10)#

Bug Fixes#

  • typesetting: Markdown math renders on GitHub as the file's own math (#446) (31ff1c3)

0.0.0-alpha.83 (2026-09-09)#

Features#

  • language: a lookup always maps into a declared dimension (#422) (533665c)

Refactoring#

  • program: a variable's domain is called domain in the program, as the file calls it (#427) (62564a2)

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#

  • typesetting: a Markdown description sets as text rather than as markup (#420) (a793961)

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#

  • the reading page says what a spec writes back out (#414) (3f4e5e0)

0.0.0-alpha.80 (2026-09-09)#

Documentation#

  • the editor recipe and the naming rules live with the language (#412) (dac95bd)

0.0.0-alpha.79 (2026-09-09)#

Bug Fixes#

  • program: two groups of a program merge with | as they did before the seal (#410) (e053e00)

0.0.0-alpha.78 (2026-09-09)#

Bug Fixes#

  • program: a lowered program pickles, and the model it came from with it (#407) (cd41ae4)

0.0.0-alpha.77 (2026-09-09)#

Features#

  • a model loads from its YAML text as well as from a file (#406) (e88a0ef)

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#

  • language: an expression the math never reads may be nonlinear and may call dual() (#395) (18020f4)

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#

  • about: the test a function has to pass to be part of this package's surface (#246) (cc1414a)

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#

  • an expression too deep to walk is refused rather than crashing (#359) (d6cee25)

0.0.0-alpha.70 (2026-09-02)#

Documentation#

  • language: only a dimension some declaration reaches needs a source (#378) (b3b9549)

0.0.0-alpha.69 (2026-09-02)#

Bug Fixes#

  • the docstrings no longer point a consumer at the package-private expression tree (#351) (15b1985)

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#

  • a model loads, lowers and typesets three to eight times faster (#357) (ea6fe79)

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#

  • program: a mask walks its leaves once and every question reads that walk (#338) (337d169)

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#

  • parser: a parsed expression cannot be rewritten under another pass (#329) (fcfb7b8)

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#

  • language: a label space may group a position, though not a reduction or a walk (#281) (00be0cb)

0.0.0-alpha.49 (2026-08-31)#

Features#

  • examples: a link delivers to as many buses as its data declares, not two (#273) (0ece0d8)

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#

  • the README's example of reading a loaded model runs as written (#240) (304a233)

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#

  • program: a program says which of the language's constructs it uses (#207) (4e55a15)

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#

  • one call returns every note the language can give without data (#191) (2face7a)

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#

  • the style guide's front-door example is the function it quotes (#187) (5dbed70)

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#

  • a program is the second public state, and one call reaches it (#177) (c9ee1ab)

0.0.0-alpha.31 (2026-08-28)#

Documentation#

  • agents: the cheap gates run here, and CI is reported rather than watched (#175) (78e3d80)

0.0.0-alpha.30 (2026-08-28)#

Documentation#

  • the absence rules cover every operator, not the three they named (#173) (3266a5b)

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#

  • the ac-dc-meshed rung states its network, so the reference run needs no download (#166) (abf734c)

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#

  • a snapshot is a timestamp, in the file and in every rung's network (#159) (dd5122e)

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#

  • a piecewise method answers which curvature it is exact for (#135) (6f0fff1)

0.0.0-alpha.21 (2026-08-26)#

Documentation#

  • language: the absence page is half the length and shows each rule on a model (#127) (147788a)

0.0.0-alpha.20 (2026-08-26)#

Documentation#

  • the language knows nothing about sinks (#118) (886a854)

0.0.0-alpha.19 (2026-08-26)#

Bug Fixes#

  • typeset: a string value in a where clause prints as a quoted label (#114) (9be22c1)

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#

  • the tree describes this package, not the project it was cut from (#94) (9673f9a)

0.0.0-alpha.16 (2026-08-25)#

Refactoring#

  • dead branches, an unused depth cap and prose about a parent project are gone (#86) (f31f3b0)

0.0.0-alpha.15 (2026-08-25)#

Documentation#

  • the title rules are written for the changelog reader (#79) (fdb52e4)

0.0.0-alpha.14 (2026-08-25)#

Documentation#

  • AGENTS.md says what a change here is held to (#76) (5e142f5)

0.0.0-alpha.13 (2026-08-25)#

Bug Fixes#

  • refuse a str or bool parameter where arithmetic wants a number (#71) (9b320fd)

0.0.0-alpha.12 (2026-08-25)#

Documentation#

  • a named offset needs no edge=, the limitation it named is gone (#68) (d91a0c3), closes #64

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#

  • pin the eight names that keep this package and its consumer in step (#51) (15a354b)

Refactoring#

  • name the groups a pass asks about, and spell each operator once (#52) (e35c46c)
  • the package is typesetting, the function stays typeset (#54) (a1d9599)

0.0.0-alpha.9 (2026-08-23)#

Features#

  • position(dim) replaces index(dim, i), converting on the left (#31) (8f78ac5)

0.0.0-alpha.8 (2026-08-23)#

Features#

  • upright is what the model is given, italic is what the solver chooses (#44) (cbccc68)

0.0.0-alpha.7 (2026-08-23)#

Bug Fixes#

  • the notation page is generated again, and something says so (#41) (3dad75e)

0.0.0-alpha.6 (2026-08-23)#

Documentation#

  • an Examples section, each model beside the math it prints (#38) (66bfae4)

0.0.0-alpha.5 (2026-08-22)#

Bug Fixes#

  • to_markdown printed TeX's em-dash ligature, not an em dash (#34) (226407a)

0.0.0-alpha.4 (2026-08-21)#

Refactoring#

  • extract the language and typeset from lpspec (#17) (b997193)

0.0.0-alpha.3 (2026-08-21)#

Bug Fixes#

  • stop prettier rewriting what release-please generates (#27) (7486555)

0.0.0-alpha.2 (2026-08-21)#

Bug Fixes#

  • the release notes landed inside an HTML comment (#25) (c33dc24)

0.0.0-alpha.1 (2026-08-21)#

Bug Fixes#

  • stop the release build silently shipping a 0.0.0 wheel (#23) (a801b00)