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

0.1.0 (2026-09-25)

🎉 specsolve is officially on PyPI!

pip install specsolve

specsolve 0.1.0 requires mathspec 0.2.0 and uses its words. A spec is the problem a file states, with no data. A model is a spec with data attached, which build returns as a Model (glossary). The messages and the docs use the two words in these senses.

Since 0.1.0rc1, this release breaks three things:

  • An archive holds its spec as spec.yaml, not model.yaml. An archive that 0.1.0rc1 wrote is refused with a LayoutError. To read one, rename its model.yaml member to spec.yaml.
  • specsolve requires mathspec 0.2.0. There, the first parameter of to_spec, advice and the typesetting functions is spec, not model, and the module mathspec.model is mathspec.spec. A call that passes model= by keyword fails. A positional call works as before.
  • Messages say "spec" where they said "model" for the file. A test that matches the old text fails.

The pull requests since 0.1.0rc1:

  • docs: the site follows the reader's light or dark setting in its own violet colour, with code, diagrams and footnotes readable in both (#1767)
  • feat!: specsolve requires mathspec 0.2.0 and uses its words spec and model, so an archive holds its spec as spec.yaml (#1768)
  • docs: every link to the language's documentation points at mathspec.readthedocs.io (#1764)
  • fix: the PyPI page links the docs, issues and changelog, and a stale saved answer says the layout moves before 1.0 (#1763)

0.1.0rc1 (2026-09-25)

The release candidate for 0.1.0, the first release on PyPI: pip install specsolve==0.1.0rc1. The 0.0.1-alpha.N releases below were tags and GitHub releases only.

  • refactor(api): specsolve no longer builds a linopy model, and its linopy extra and LaneError are gone (#1755)
  • docs: the solve example archives its run and reads it back, with annotations that name the other options (#1748)

0.0.1-alpha.359 (2026-09-25)

Documentation

  • the configuration files keep a one-line reason only where a setting would look like a mistake (#1756) (7491f91)

0.0.1-alpha.358 (2026-09-25)

Documentation

  • a tutorial feeds the dispatch model from parquet, reads the answer as tables and queries its archive (#1747) (5ecc2ec)
  • a tutorial solves one model once per scenario and then window by window (#1746) (7c15f18)
  • the readme and home page lead with four benefits for energy system modellers, in cards with icons, and the readme is under half its length (#1743) (e14f3b8)

0.0.1-alpha.357 (2026-09-25)

Features

  • language: an open bound is null and an infinite bound is refused, the way mathspec 0.0.0-alpha.127 does (#1744) (1b1dbef)

0.0.1-alpha.356 (2026-09-25)

Documentation

  • the glossary says a model holds no data, as math-spec uses the word, and every link into math-spec's docs resolves (#1740) (da3f211)

0.0.1-alpha.355 (2026-09-25)

Features

  • api: a result hands back how its solve terminated as one Record (#1738) (c6ffe74)

0.0.1-alpha.354 (2026-09-25)

Refactoring

  • api: a sweep's answer is a Sweep, read back with load_sweep and scan_sweep (#1732) (24b1238)
  • api: how each slice of a sweep terminated is runs.record, saved as record.parquet, so objective always means the number (#1731) (7c14833)

Documentation

  • the glossary defines answers, sweeps, relations and assumptions, and no longer shows build taking a Program (#1730) (25d594b)

0.0.1-alpha.353 (2026-09-24)

Documentation

  • data is attached to a spec everywhere, so bound only ever means a limit (#1728) (ecf1019)

0.0.1-alpha.352 (2026-09-24)

Refactoring

  • api: the package is named specsolve, installed and imported under that name (#1726) (a9aea61)

0.0.1-alpha.351 (2026-09-23)

Features

  • language: a special-ordered set names its dimension with along, the way math-spec 0.0.0-alpha.120 does (#1720) (fdc47c5)

0.0.1-alpha.350 (2026-09-23)

Features

  • language: a where may read a predicate through a relation with at() (#1718) (cfaa01b)

0.0.1-alpha.349 (2026-09-22)

Features

  • api: a curve is written out before a verb reads it, and a sink with no SOS concept refuses a set rather than rewriting it (#1713) (7516597)

Bug Fixes

  • api: the language refuses a curve left as written, so the door no longer has to (#1714) (8021377)

0.0.1-alpha.348 (2026-09-22)

Refactoring

  • data: the caller binds every parameter a piecewise curve reads, and no name the expansion invented (#1711) (7496de9)

0.0.1-alpha.347 (2026-09-22)

Features

  • language: a model states what it assumes of its data, and a where may compare arithmetic, count coordinates and shift a predicate (#1707) (e107514)

0.0.1-alpha.346 (2026-09-21)

Bug Fixes

  • language: a pullback that reads a column over the dimension it joins on is refused at load (#1703) (e92827f)

0.0.1-alpha.345 (2026-09-19)

Refactoring

  • only the linopy lane and the solver sinks say Any (#1699) (067f14d)

0.0.1-alpha.344 (2026-09-19)

Documentation

  • the site is built by zensical, and the two tutorials run as pages rather than notebooks (#1693) (48633b2)

0.0.1-alpha.343 (2026-09-18)

Features

  • language: a call through a relation names the columns it walks, so a relation may gain a value column without changing what the call means (#1691) (451b7c7)

0.0.1-alpha.342 (2026-09-18)

Bug Fixes

  • api: an archive in a run=<name> directory stamps the name the path gives (#1689) (7fc0251)

0.0.1-alpha.341 (2026-09-18)

Features

  • api: an answer says which data it came back from, not just which spec (#1672) (f66fffc)

0.0.1-alpha.340 (2026-09-18)

Features

  • api: an infeasible solve says why there is no solution, so a feasibility cut needs no second model (#1682) (7cc52eb)

0.0.1-alpha.339 (2026-09-18)

Features

  • language: a relation declares key columns and value columns (#1681) (df67ebc)

0.0.1-alpha.338 (2026-09-18)

Documentation

  • the decomposition page shows the loop the example runs, and says lpspec owns no driver (#1678) (f1d33b3)

0.0.1-alpha.337 (2026-09-16)

Bug Fixes

  • engine: a cased quantity summed onto a constant side builds, and the coverage guards have one home (#1665) (96a437d)

0.0.1-alpha.336 (2026-09-16)

Features

  • engine: the relational lane builds every shape of relation the language admits (#1659) (88914c4)

0.0.1-alpha.335 (2026-09-16)

Bug Fixes

  • data: a relation whose two columns are over one dimension builds (#1657) (2f96905)

0.0.1-alpha.334 (2026-09-15)

Features

  • language: a model states its topology as relations, the way math-spec 0.0.0-alpha.89 does (#1646) (1fd8926)

0.0.1-alpha.333 (2026-09-15)

Bug Fixes

  • a polars without the streaming engine still solves and reads back (#1644) (c47ae6c)

0.0.1-alpha.332 (2026-09-15)

Documentation

  • the about pages and the model pages say each fact once, in sentences of one idea (#1640) (5d4efa3)
  • the howtos, tutorials and reference say each fact once and drop the argument for it (#1639) (697f29d)

0.0.1-alpha.331 (2026-09-15)

Features

  • language: a variable, a constraint and a cased expression declare their shape as dims, as a parameter does (#1634) (7bdcdeb)

0.0.1-alpha.330 (2026-09-15)

Documentation

  • the language closes its own gaps instead of offering an escape hatch (#1631) (72928bd)

0.0.1-alpha.329 (2026-09-14)

Bug Fixes

  • compat: a constant beside a variable term is refused where its data is short (#1621) (545ed6d)

0.0.1-alpha.328 (2026-09-14)

Documentation

  • bench: the benchmark page publishes the newest run, and says where that run left a gap (#1618) (089f816)

0.0.1-alpha.327 (2026-09-14)

Performance

  • engine: a model is hashed for a re-solve only once a re-solve is reached (#1608) (8d27e88)

0.0.1-alpha.326 (2026-09-14)

Documentation

  • howto: reading a directory of runs is its own page (#1611) (88105f5)

0.0.1-alpha.325 (2026-09-13)

Features

  • api: an archive says which data it was solved over and what the solve took (#1601) (758e71f)

0.0.1-alpha.324 (2026-09-13)

Features

  • api: load reads an archive whole, and scan leaves it on disk (#1603) (001de65)

Performance

  • engine: a build stops hashing labels it can count (#1589) (bc49db5)
  • engine: a magnitude is read off each side of a column instead of being built (#1592) (019e22c)
  • engine: a model reaches HiGHS in one call instead of a batch at a time (#1591) (77ccb7d)

Documentation

  • api: the glossary defines load and scan, and the tree spells each name one way (#1604) (3d43f6d)
  • the published speed claims match the measurements behind them (#1586) (cb98d58)

0.0.1-alpha.323 (2026-09-12)

Features

  • api: an archived answer says which run it came from and when, in one record file (#1585) (650a3ad)

0.0.1-alpha.322 (2026-09-12)

Features

  • api: an archive records how big the model was and how long it took (#1598) (80f6a6e)

0.0.1-alpha.321 (2026-09-12)

Documentation

  • bench: the benchmark page is re-taken from the newest run, its claims about the numbers included (#1587) (0210774)

0.0.1-alpha.320 (2026-09-11)

Features

  • api: a model, its data and its answer are one file that reads back into polars or a database (#1579) (8dc36f9)
  • api: two names that differ only by case are refused, whichever verb reads the spec (#1582) (fc19d17)

0.0.1-alpha.319 (2026-09-10)

Features

  • data: a lookup maps into a declared dimension rather than owning its values (#1576) (005b106)

0.0.1-alpha.318 (2026-09-10)

Features

  • strategy: a rolling horizon may keep a different number of coordinates in each window (#1572) (e52bc2d)

Bug Fixes

  • strategy: a carry hands on the last row a slice owns rather than a coordinate the caller names (#1571) (561d05c)
  • strategy: a hand-built axis refuses the stitched answer rather than returning the keyed one (#1568) (7332207)

0.0.1-alpha.317 (2026-09-10)

Documentation

  • descriptions set as prose under math-spec's escaping, pinned to the head of energy-models/math-spec#421 (#1565) (5c6b606)

0.0.1-alpha.316 (2026-09-10)

Documentation

  • the About pages keep each rule and drop the story behind it (#1564) (ec09ace)

0.0.1-alpha.315 (2026-09-09)

Documentation

  • each shared claim has one page, and two how-tos cover a parallel sweep and a wrong answer (#1561) (7dc8553)
  • every hand-written page meets the docs-writing skill, and the tree follows the nav (#1560) (645a346)

0.0.1-alpha.314 (2026-09-09)

Documentation

  • the site nav is arranged by what a page is for rather than by subject (#1558) (6d346c5)

0.0.1-alpha.313 (2026-09-09)

Refactoring

  • api: every verb says in its signature what a source and a slice key may be (#1554) (3767f7a)

0.0.1-alpha.312 (2026-09-09)

Features

  • strategy: a lowered program crosses a process, so a pooled sweep lowers nothing twice (#1549) (09cd887)

0.0.1-alpha.311 (2026-09-09)

Features

  • strategy: a sweep spills each slice to disk and resumes where it stopped, and every export and bridge reads every kind (#1547) (c5b4828)

0.0.1-alpha.310 (2026-09-08)

Bug Fixes

  • strategy: a sweep takes every source shape solve takes, and a carry that cannot start is refused before a slice is cut (#1543) (b56f8f2)

0.0.1-alpha.309 (2026-09-08)

Refactoring

  • api: a sweep's slice statuses have one name rather than two (#1540) (9dfe10b)

0.0.1-alpha.308 (2026-09-08)

Features

  • strategy: a sweep asks the model what a window can bear before it cuts one (#1514) (d77cdfb)

0.0.1-alpha.307 (2026-09-08)

Bug Fixes

  • linopy: a comparison with its terms on the right builds, and so does a window whose width no lookup reaches (#1537) (46e29cc)

0.0.1-alpha.306 (2026-09-08)

Bug Fixes

  • engine: a variable declared absence: zero reads as zero under a nonlinear operator (#1532) (038af9e)

0.0.1-alpha.305 (2026-09-08)

Features

  • api: a named expression is read back at any degree and may read a constraint's dual (#1529) (b946506)

0.0.1-alpha.304 (2026-09-03)

Features

  • api: a badly scaled bound names the declaration that holds it (#1525) (b8546fa)

0.0.1-alpha.303 (2026-09-02)

Bug Fixes

  • data: a hole on a constant side is refused even under a sum (#1523) (caa3627)

0.0.1-alpha.302 (2026-09-02)

Documentation

  • architecture: the plan-node census covers expression nodes, not only predicates (#1505) (c4a5b94)

0.0.1-alpha.301 (2026-09-02)

Bug Fixes

  • data: a convex piecewise curve is checked without xarray, so a bare install attaches it (#1507) (8b50241)

Refactoring

  • data: a caller's data is read and checked once, at one door, for both lanes (#1506) (787f9c7)

0.0.1-alpha.300 (2026-09-02)

Performance

  • deps: every build spends less time reading and lowering the model file (#1503) (48d1a7a)

0.0.1-alpha.299 (2026-09-01)

Performance

  • engine: a model builds faster for each declaration it carries (#1500) (9126391)

0.0.1-alpha.298 (2026-09-01)

Documentation

  • bench: the published numbers come from a run of main, and the reproduction installs that commit (#1497) (99a7633)

0.0.1-alpha.297 (2026-09-01)

Features

  • bench: a cell that exhausts the machine is recorded, not lost (#1480) (8a332e0)

0.0.1-alpha.296 (2026-09-01)

Documentation

  • bench: the published numbers come from one run of a box the project can rebuild (#1488) (bb51e4d)

0.0.1-alpha.295 (2026-09-01)

Refactoring

  • api: data attaches to a spec, so bound means only a variable's limit (#1479) (9583701)

0.0.1-alpha.294 (2026-09-01)

Refactoring

  • api: the input is a spec, a Model is that spec with your data (#1474) (0fdf674)

0.0.1-alpha.293 (2026-08-31)

Bug Fixes

  • differential: a rung's projection names its quantities in the file's order, so a tree nobody changed stops going red (#1469) (1603efa)

0.0.1-alpha.292 (2026-08-31)

Features

  • language: a quantity defined by cases may mix a constant, a parameter and a variable across its regions (#1464) (482e9ec)

0.0.1-alpha.291 (2026-08-31)

Documentation

  • bench: the box's own housekeeping is turned off before it is snapshotted (#1461) (6e011f8)

0.0.1-alpha.290 (2026-08-31)

Bug Fixes

  • bench: a case hands back what it measured before the next one can take the box (#1455) (365ced0)

0.0.1-alpha.289 (2026-08-29)

Bug Fixes

  • bench: the kill reaches the spawned child that is holding the model (#1453) (e91c844)

0.0.1-alpha.288 (2026-08-28)

Bug Fixes

  • bench: a cell too big for the box takes the case down, not the runner (#1451) (58e073f)

0.0.1-alpha.287 (2026-08-28)

Bug Fixes

  • bench: a cell the memory budget stopped says so, instead of naming the seconds (#1447) (e16fc0b)
  • bench: the scaling chart reads only the ceilings of the ladder it draws (#1446) (5991e91)

0.0.1-alpha.286 (2026-08-28)

Features

  • api: check hands back the plan the other verbs take, so a model is lowered once per run (#1443) (371bade)

Bug Fixes

  • differential: a dual the file writes negated is held to the negative of PyPSA's rather than excused (#1444) (8f68665)

0.0.1-alpha.285 (2026-08-28)

Documentation

  • an infeasible model whose file still reads right is diagnosed by the row it built (#1440) (82f4485)
  • examples: the PyPSA ladder is the fifteen rungs, and the gallery is examples rather than a second ladder (#1441) (ff525e4)

0.0.1-alpha.284 (2026-08-28)

Bug Fixes

  • data: a negative window width is refused at load, and a spelled-out AND True builds (#1432) (aeab021)

0.0.1-alpha.283 (2026-08-28)

Documentation

  • every type and module the documentation names is one that exists (#1427) (91c9b7c)

0.0.1-alpha.282 (2026-08-28)

Performance

  • bench: the rebuild pass is measured once, not once per sink (#1425) (2b876f7)

0.0.1-alpha.281 (2026-08-28)

Performance

  • bench: the memory pass builds the model once instead of four times (#1420) (3e9c67c)

0.0.1-alpha.280 (2026-08-28)

Bug Fixes

  • bench: a case does not carry the last one's memory into the next (#1417) (6b5c103)

0.0.1-alpha.279 (2026-08-28)

Documentation

  • engine: the program's own rules read without knowing what builds it (#1413) (6cd559b)

0.0.1-alpha.278 (2026-08-28)

Refactoring

  • engine: a program states what it means, so the direction and the edge cannot be inferred wrongly (#1411) (bf67cc4)

Documentation

  • agents: the cheap gates run here, and CI is reported rather than watched (#1410) (6c1d91c)

0.0.1-alpha.277 (2026-08-28)

Performance

  • linopy: a trailing window merges its lags once instead of one at a time (#1341) (f225422)

0.0.1-alpha.276 (2026-08-28)

Features

  • engine: a malformed plan is refused at the boundary, in plan vocabulary, before any query compiles (#1394) (e435d63)
  • engine: the plan says what type a dimension's labels are, as it already says so for a parameter's values (#1391) (05c07f5)

Refactoring

  • compat: the linopy lane builds from the logical plan, so one lowering answers for both lanes (#1385) (995fa34)
  • compat: the linopy loader reads its declarations off the plan, so the plan and the data are the whole seam (#1388) (a20a042)
  • engine: a shape operator declares its own fan-in, and the absence pass reads it (#1395) (beaace8)
  • engine: one walk over a plan's expressions, and every question about one is a filter of it (#1398) (5c7f2a0)
  • engine: the expression nodes are one closed type, so a walk that forgets one no longer compiles (#1397) (e8be601)
  • engine: the plan answers which dimension a lookup labels, instead of five callers walking for it (#1387) (8d4cd28)
  • engine: the plan decides what a file may say, and the engine only builds it (#1400) (a5582fe)
  • engine: two plan fields say what rule holds them, rather than what they saved a lookup on (#1402) (79c8961)

Documentation

  • the plan's thirteen nodes are one table, each with the query and the linopy call it becomes (#1396) (0e0ae80)

0.0.1-alpha.275 (2026-08-27)

Features

  • differential: rung 14 binds — a network with scenarios flattens to the file's dimensions, and a name PyPSA spells per scenario is held per label (#1376) (ffd53ce)
  • differential: rung 15 binds — a multi-period network flattens to one snapshot axis, and PyPSA's network is solved under the semantics PyPSA speaks (#1379) (4fb41cc)
  • differential: rungs 12 and 13 bind — the tightening mask and the tangent loss fan in prep, and a block over a segment dimension held to PyPSA's row per segment (#1373) (90d7df2)

0.0.1-alpha.274 (2026-08-27)

Refactoring

  • linopy: a grouped sum's empty group is filled by the caller rather than by a hand-written storage row (#1375) (bb50cb0)

0.0.1-alpha.273 (2026-08-27)

Refactoring

  • differential: snapshots join PyPSA's timestamps natively, the position map is gone (#1369) (00c1da1)

0.0.1-alpha.272 (2026-08-27)

Refactoring

  • linopy: the empty sum is built through linopy's public constructor rather than its storage layout (#1365) (88de413)

0.0.1-alpha.271 (2026-08-27)

Features

  • differential: the commitment rung compares model for model, with its deliberate differences recorded (#1360) (eeeb149)
  • differential: the structure column holds the solver model's rows, columns and nonzeros equal on both sides (#1362) (24a73b0)

Bug Fixes

  • linopy: a sum whose term carries an empty dimension is the empty sum rather than an error (#1359) (a7a3040)

0.0.1-alpha.270 (2026-08-27)

Features

  • differential: each rung has its own model, the file projected onto what the rung builds and held to its objective (#1338) (0400235)
  • differential: the ladder holds each PyPSA name to one block with an equal count rather than a sum over its splits (#1351) (46050c3)
  • differential: the ladder holds every constraint's dual to PyPSA's, and a difference needs a recorded reason (#1352) (dc37007)

Documentation

  • differential: the PyPSA ladder page shows the tables each rung binds, committed and held to the corpus (#1336) (cbd00a3)
  • differential: the PyPSA ladder, one page per rung, held to PyPSA by objective, structure, duals and the linopy lane (#1348) (a72cc75)

0.0.1-alpha.269 (2026-08-26)

Bug Fixes

  • linopy: a parameter with no dimensions keeps the type it declares (#1340) (89f57f1)

0.0.1-alpha.268 (2026-08-26)

Bug Fixes

  • differential: a stamp moves when its claim changes, not when the solver returns different bits (#1333) (a890c11)

0.0.1-alpha.267 (2026-08-26)

Refactoring

  • differential: the pypsa corpus lives beside its runner, and the certificate is a committed file this tree must reproduce (#1328) (1e0aa53)

0.0.1-alpha.266 (2026-08-26)

Bug Fixes

  • data: a piecewise method's exact curvature is the language's answer, not this package's copy (#1323) (99994a5)
  • differential: the KVL basis is PyPSA's own cycle matrix, and the objective is compared net of its constant (#1322) (9b2aa70)

0.0.1-alpha.265 (2026-08-26)

Features

  • differential: the pypsa runner holds the nodal prices to PyPSA's (#1318) (b45bf15)
  • the pypsa differential suite lives here, and the corpus keeps only documents (#1310) (c1db712)

Bug Fixes

  • bench: the scheduled ladder measures the selection it was given, not pytest's defaults (#1312) (3150844)
  • differential: the pypsa runner certifies the rung folders, and refuses an empty corpus (#1313) (2092629)

0.0.1-alpha.264 (2026-08-26)

Bug Fixes

  • linopy: a sum_back window whose every width is zero builds no row instead of crashing (#1307) (5525e7c)

0.0.1-alpha.263 (2026-08-26)

Refactoring

  • api: check tells a lane from a sink in one place (#1295) (6392a09)

Documentation

  • agents: a break is described in the PR body, and a verified claim names its gate (#1301) (e385dcc)

0.0.1-alpha.262 (2026-08-26)

Bug Fixes

  • solver: a gurobi solver releases its model and licence however it is dropped (#1292) (f33c3e9)

Refactoring

  • solver: every solver states what it holds and releases it the same way (#1297) (ab848b7)

0.0.1-alpha.261 (2026-08-26)

Bug Fixes

  • bench: a time budget decides one ladder without deciding the other (#1285) (84850d9)

Documentation

  • api: a docstring citing a hard rule says where the rules are (#1296) (2560343)

0.0.1-alpha.260 (2026-08-26)

Refactoring

  • api: check lowers the expressions of the model it lowers against (#1290) (efc8e01)

0.0.1-alpha.259 (2026-08-26)

Refactoring

  • the package and its test suite state each shared fact once (#1284) (2065436)

0.0.1-alpha.258 (2026-08-25)

Features

  • bench: a table shows the arms the run measured, not the two it was written for (#1271) (29b84a3)

0.0.1-alpha.257 (2026-08-25)

Documentation

0.0.1-alpha.256 (2026-08-25)

Features

  • bench: every measurement is a row, so a plot is a filter not a patch (#1265) (99de9ed)

Bug Fixes

  • bench: a rename in src cannot retire a bench entry point unnoticed (#1267) (7a72612)

Refactoring

  • bench: an arm is a module, not a branch in three verbs (#1264) (e62cc33)
  • bench: the eager lane is not one of the libraries we compare against (#1268) (37ca9c3)

0.0.1-alpha.255 (2026-08-25)

Features

  • api: the types the verbs return can be named (#1262) (1b39969)

0.0.1-alpha.254 (2026-08-25)

Features

  • operators: a window may stop at each group's edge (#1260) (027345c)

0.0.1-alpha.253 (2026-08-25)

Refactoring

  • architecture: each layer holds what its docstring says it holds (#1257) (d3fa90a)

0.0.1-alpha.252 (2026-08-24)

Bug Fixes

  • diagnostics: a build that raises says which half of the report survived (#1252) (216cd2d)

Documentation

  • api: diagnostics() says what it answers with when a build raised (#1253) (b4d91b9)

0.0.1-alpha.251 (2026-08-24)

Refactoring

  • data: a curve's numbers are checked somewhere of their own (#1236) (d69dad1)
  • engine: a build is a value, so the engine holds one field not twenty-six (#1245) (3daf67d)
  • engine: a where-mask is its own vocabulary, not a method (#1240) (fde62ee)
  • engine: walking a dimension's own order is one subject, not nine methods (#1244) (cf229e6)
  • engine: what a term is stops being the compiler's business (#1234) (49b655f)
  • linopy: the builder builds; it stops also being the operator table (#1235) (dfb6283)
  • lowering: a walk stops handing itself the same three arguments (#1249) (5db1df9)
  • lowering: each built-in lowers in a function with its own name (#1247) (7c009d1)

Documentation

  • refactor: the modules that moved stop being described where they were (#1250) (e3cc1e0)

0.0.1-alpha.250 (2026-08-24)

Refactoring

  • tests: the whole repository imports the language by the surface it pins (#1237) (e6e1d72)

0.0.1-alpha.249 (2026-08-23)

Features

  • language: a boundary clause names a position, not the label at one (#1230) (3e018da)

0.0.1-alpha.248 (2026-08-21)

Documentation

  • architecture: the map describes the tree the cut left behind (#1227) (a987491)

0.0.1-alpha.247 (2026-08-21)

Documentation

  • the site's sections are the three subjects this package still has (#1226) (2b04cb3)

0.0.1-alpha.246 (2026-08-21)

Refactoring

  • language: the language is a dependency, not a directory (#1223) (ffbbee6)

0.0.1-alpha.245 (2026-08-21)

Bug Fixes

  • tests: the renderer's tests read only what travels with it (#1217) (c486fff)

0.0.1-alpha.244 (2026-08-21)

Refactoring

  • tests: the sweep's rules are readable one at a time (#1213) (fd3df65)

0.0.1-alpha.243 (2026-08-21)

Features

  • tools: a mutation table is produced rather than claimed (#1199) (8a50254)

0.0.1-alpha.242 (2026-08-21)

Refactoring

  • tests: a test is named for its construct, and the residue file is split (#1209) (935bfd7)
  • tests: the relational tests say what each group shares (#1211) (c389f6c)

Documentation

  • agents: coverage is a local instrument, and the tree says so (#1207) (a1dc544)

0.0.1-alpha.241 (2026-08-21)

Documentation

  • language: a consumer of the AST has a page to read the contract in (#1205) (4e05dc6)

0.0.1-alpha.240 (2026-08-21)

Bug Fixes

  • linopy: reading a named expression over a masked curve derives its mask (#1202) (a83883b)

0.0.1-alpha.239 (2026-08-21)

Features

  • language: a model still owing declarations cannot reach a builder (#1200) (5f53d6d)

Documentation

  • ceiling: the spec's ceiling names no solver (#1196) (992f1aa)

0.0.1-alpha.238 (2026-08-20)

Documentation

  • a docstring names the number it measured and the symbol that exists (#1195) (343ea93)

0.0.1-alpha.237 (2026-08-20)

Refactoring

  • errors: a refusal with one raiser is worded where it is raised (#1189) (477ae47)

0.0.1-alpha.236 (2026-08-20)

Documentation

  • a shown model, a key and a count each say what the tree says (#1192) (2b89ebf)

0.0.1-alpha.235 (2026-08-20)

Features

  • data: a lookup's map has one data transport, not two (#1185) (65079b6)

Refactoring

  • data: a lookup's values are checked once, not once per lane (#1190) (73c8bf6)
  • engine: an unmapped label is a row that is not there, inside as well (#1187) (903ec33)

0.0.1-alpha.234 (2026-08-20)

Bug Fixes

  • data: a map joined onto an index leaves its label order alone (#1184) (3116666)

0.0.1-alpha.233 (2026-08-20)

Features

  • api: check answers whether a named sink will take the model (#928) (4a9d80e)
  • language: a constraint may be quadratic where something can build one (#942) (7ef15c7)
  • language: a discount factor is arithmetic, not a column to prepare (#1177) (6c5c806)
  • language: the objective takes a quadratic term (#929) (e8c88cb)
  • sinks: a sink declares what it can ingest, and what it refuses in pairs (#927) (3af0c43)
  • solver: gurobi takes the quadratic objectives highs refuses (#930) (344804b)

Documentation

  • sinks: the capability table says what each sink actually refuses (#925) (8e0b7c8)

0.0.1-alpha.232 (2026-08-20)

Features

  • data: a lookup is supplied without rewriting the index it rides on (#1179) (385c048)

0.0.1-alpha.231 (2026-08-20)

Documentation

  • examples: a curve whose arity is data is four declarations (#1131) (9cae48d)

0.0.1-alpha.230 (2026-08-20)

Bug Fixes

  • language: a constraint that decides nothing is refused where the file is read (#1173) (c94d330), closes #1171
  • typeset: a fill and a group share the operator's one subscript (#1169) (8455a73), closes #1165

0.0.1-alpha.229 (2026-08-20)

Bug Fixes

  • compat: a reduction over an empty dimension builds no row on either lane (#1170) (7e348a1), closes #1108

0.0.1-alpha.228 (2026-08-20)

Bug Fixes

  • language: a per-group offset translates each group by its own lag (#1166) (2b80850), closes #1161

0.0.1-alpha.227 (2026-08-20)

⚠ BREAKING CHANGES

  • language: a piecewise gate is named for the number it is (#1136)

Bug Fixes

  • language: a piecewise curve whose gate does not exist there is ungated, not relaxed (#1159) (1b927cc)
  • release: the alpha stream holds against a breaking commit title (#1162) (27f03c3)

Refactoring

  • language: a piecewise gate is named for the number it is (#1136) (ef119f2)

0.0.1-alpha.226 (2026-08-20)

Documentation

  • language: the rule that decides what belongs has its own page (#1153) (f5c5336)

0.0.1-alpha.225 (2026-08-20)

Refactoring

  • extraction: the corpus that moves is the operator reference's source (#1149) (a71eb62)

0.0.1-alpha.224 (2026-08-20)

Refactoring

  • tools: a generator that reads only the language lives with it (#1147) (810f1bd)

0.0.1-alpha.223 (2026-08-20)

Bug Fixes

  • engine: four operators refuse a constant beside a term as a lane gap (#1140) (b59aa4c)
  • engine: sum_back drops a constant at a slot its term is absent from (#1143) (2845133)

Refactoring

  • errors: the language raises its own errors (#1135) (38c00af)
  • language: the AST is read through one declared surface (#1132) (fd8bfb1)

0.0.1-alpha.222 (2026-08-20)

Features

  • api: a single constraint row has a spelling (#1114) (54bd9e4)

0.0.1-alpha.221 (2026-08-20)

Features

  • language: a curve shorter than its breakpoint dimension says so (#1115) (45dc672)
  • language: a curve's length is a fact of the curve (#1117) (3996273)

Bug Fixes

  • data: a breakpoint dimension with no index keeps its own message (#1125) (0ffef63)
  • data: a piecewise curve is judged as the model builds it (#1126) (c23102b)
  • language: a curve varying along a dim no link carries is named on the link (#1127) (a51c151)

Documentation

  • examples: a gallery model whose curves are not all the same length (#1119) (1e9e7d1)

0.0.1-alpha.220 (2026-08-19)

Features

  • data: a parameter's dims arrive in columns, never in a pandas index (#1088) (d06a601)

Refactoring

  • data: both lanes read their data through one front door (#1076) (8923df9)
  • linopy: the builder groups by what it translates (#1092) (380cdbe)

0.0.1-alpha.219 (2026-08-19)

Documentation

  • language: the short-curve remedy names the two methods that refuse it (#1111) (a22f099)

0.0.1-alpha.218 (2026-08-19)

Features

  • solver: a model arrives on the solver its author licences (#1107) (262872a)

0.0.1-alpha.217 (2026-08-19)

Bug Fixes

  • data: a piecewise curve short of a breakpoint is refused, not read as the origin (#1105) (af93d7e)

0.0.1-alpha.216 (2026-08-19)

Features

  • file-out: a model leaves as MPS, not only as LP (#1097) (76dc58b)
  • language: a convex cost curve stops paying a variable per breakpoint (#926) (50d1984)

0.0.1-alpha.215 (2026-08-19)

Features

  • language: a capacity limit may be grouped by location and technology at once (#899) (2cabc65)

0.0.1-alpha.214 (2026-08-19)

Documentation

  • errors: the error table names every class a caller can catch (#1095) (497aa56)

0.0.1-alpha.213 (2026-08-19)

Features

  • language: check names the variable that makes a model unbounded (#909) (7781e22)

0.0.1-alpha.212 (2026-08-19)

Bug Fixes

  • compat: the lane says in its own words what it cannot build (#1087) (b6a90df)

0.0.1-alpha.211 (2026-08-19)

Refactoring

  • language: a closed vocabulary is a type, not a string plus a check (#1083) (92f615e)

0.0.1-alpha.210 (2026-08-19)

Features

  • language: a sum can take every dim its operand carries (#1071) (9874d64)
  • language: an objective spells the sums that make it one number (#1077) (d40ca88)

0.0.1-alpha.209 (2026-08-19)

Features

  • language: the YAML surface has a machine-readable schema (#718) (d3c2611)

0.0.1-alpha.208 (2026-08-19)

Bug Fixes

  • language: a coordinate in no group is absent, not an edge the fill speaks for (#1070) (60e3574)

0.0.1-alpha.207 (2026-08-19)

Performance

  • ci: the LaTeX gate stops costing a minute a run (#1075) (661e7e0)

0.0.1-alpha.206 (2026-08-19)

Bug Fixes

  • packaging: the linopy extra resolves again after upstream merged v1 (#1073) (aafac01)

0.0.1-alpha.205 (2026-08-18)

Features

  • api: diagnostics says which parameters arrived short of their dims (#1067) (c904400)

0.0.1-alpha.204 (2026-08-18)

Bug Fixes

  • compat: the eager lane's edge fills the shift's own vacated slot (#1050) (3f965f7)
  • engine: a per-entity offset's edge is per entity (#1053) (53fc3f7)

0.0.1-alpha.203 (2026-08-18)

Features

  • ports: a data column decides which boundary regime a storage obeys (#1038) (9879cde)

0.0.1-alpha.202 (2026-08-18)

Bug Fixes

  • tests: the golden objective reaches the grouping the walk does (#1056) (db7b3fb)

Refactoring

  • ports: a pre-horizon state of zero is an edge, not a block (#1057) (dd12a37)

Documentation

  • typeset: every construct is on one page, as the math it prints (#1039) (8c6bcca)

0.0.1-alpha.201 (2026-08-18)

Bug Fixes

  • language: a divisor that adds is refused at load, not at build (#1048) (4153653)
  • typeset: an objective term is shown summed over the dims it carries (#1045) (3e29596)

0.0.1-alpha.200 (2026-08-18)

Features

  • ports: a risk preference is three variables and two rows (#1035) (c3972ff)
  • ports: capacity is chosen once and dispatch once per future (#1033) (96a4572)

0.0.1-alpha.199 (2026-08-18)

Bug Fixes

  • api: a bridge out of a bare install says which extra to add (#1029) (ce60c03)

Documentation

  • ceiling: a tracked-metric vocabulary is a dimension and a named expression (#1031) (ab9d241)

0.0.1-alpha.198 (2026-08-18)

Bug Fixes

  • engine: a group with no members caps a row instead of refusing it (#1027) (31ab50a)

0.0.1-alpha.197 (2026-08-18)

Features

  • api: a badly scaled model says which declaration is badly scaled (#993) (ab92e2e)
  • data: a declared dtype is what the column has to be (#1022) (acbe2e6)

0.0.1-alpha.196 (2026-08-18)

Features

  • language: a translation stops at the edge of its own group (#1023) (aa747b5)

0.0.1-alpha.195 (2026-08-18)

Features

  • language: a boundary names its position inside each group (#1013) (f6ccac4)

Refactoring

  • language: by= names a lookup, and an offset has a word of its own (#1016) (ce13026)

0.0.1-alpha.194 (2026-08-18)

Bug Fixes

  • data: a fractional offset no longer truncates to the position below it (#1005) (b453c51)

0.0.1-alpha.193 (2026-08-18)

Documentation

  • language: one home for the binding rule, one page for the two grammars (#1010) (e004661)

0.0.1-alpha.192 (2026-08-18)

Bug Fixes

  • data: a row carrying no value is refused on both lanes (#1001) (795b26f)

0.0.1-alpha.191 (2026-08-18)

Bug Fixes

  • examples: every seeding clause names the position, not the label (#1004) (4f57d5a)

0.0.1-alpha.190 (2026-08-18)

Features

  • language: a boundary seed survives the index being relabelled (#904) (ca76c5a)
  • ports: what may be built in a period depends on the period before (#995) (208e9e7)

Bug Fixes

  • tests: the boundary suite binds its index the way sources does (#1002) (9da3b02)

Documentation

  • linopy: the one construct the eager lane accepts and cannot build (#990) (e25af73)

0.0.1-alpha.189 (2026-08-17)

Features

  • ports: a committed unit whose capacity is built declares its big-M (#991) (98fd368)

Bug Fixes

  • engine: a pullback through a null lookup no longer binds its row at zero (#988) (578868c)

Refactoring

  • examples: an edge leg is named for the edge set it belongs to (#973) (810a702)

0.0.1-alpha.188 (2026-08-17)

Features

  • ports: an asset exists for the periods its lifetime covers (#975) (0b33d9f)

0.0.1-alpha.187 (2026-08-17)

Features

  • ports: a global limit is a sum over a selected set (#967) (42f6e57)

0.0.1-alpha.186 (2026-08-17)

Features

  • ports: a link may deliver later than it withdrew (#980) (6e599eb)

0.0.1-alpha.185 (2026-08-17)

Bug Fixes

  • compat: at() through a label that maps nowhere drops the row, not the coordinate (#969) (89587ce)
  • engine: a row a propagated absence deleted is an omission too (#981) (0851444)

Documentation

  • benchmarks: the published peak says which arm pays the allocator (#970) (c84b394)

0.0.1-alpha.184 (2026-08-17)

Features

  • ports: a transmission loss is a fan of tangents, not a piecewise curve (#964) (3fb4079)

0.0.1-alpha.183 (2026-08-17)

Documentation

  • language: a propagated absence is a different event from an emptied row (#945) (409cea0)

0.0.1-alpha.182 (2026-08-17)

Features

  • language: a variable declares whether its absence is zero or undefined (#950) (adfcd8b)

0.0.1-alpha.181 (2026-08-17)

Features

  • api: a dimension's labels arrive in sources, like every other input (#956) (d30890f)

0.0.1-alpha.180 (2026-08-17)

Features

  • ports: integrality is one declaration and nothing above it cares (#943) (f14b5fc)

0.0.1-alpha.179 (2026-08-17)

Features

  • ports: a committed unit must stay on for its own window (#941) (051797a)

0.0.1-alpha.178 (2026-08-17)

Bug Fixes

  • examples: the ports row is one row, not three merges of it (#958) (eb7926b)

0.0.1-alpha.177 (2026-08-17)

Features

  • ports: a Store is one signed power with no rating of its own (#940) (5f4b775)

0.0.1-alpha.176 (2026-08-17)

Features

  • ports: storage that may spill has a second sink (#939) (d457b0e)

0.0.1-alpha.175 (2026-08-17)

Features

  • ports: a dispatch or a capacity fixed by data pins only the rows it has (#938) (d2a27d5)

0.0.1-alpha.174 (2026-08-17)

Features

  • ports: an energy total over the whole horizon is a bound (#936) (33fee41)

0.0.1-alpha.173 (2026-08-17)

Features

  • ports: capacity that comes in whole modules is an integer count (#935) (e55603f)

0.0.1-alpha.172 (2026-08-17)

Bug Fixes

  • language: a lookup's map says how labels map, not which exist (#937) (c50596f)

0.0.1-alpha.171 (2026-08-17)

Documentation

  • examples: a model beside the ladder is not listed as a rung (#947) (470eaf1)

0.0.1-alpha.170 (2026-08-16)

Features

  • language: a dimension's index has one home, declared or supplied (#908) (170e58a), closes #907 #895

0.0.1-alpha.169 (2026-08-16)

Refactoring

  • plan: the relational lane spells a lookup the way the language does (#903) (f1a4b76)

Documentation

  • data: the precedence list and its closing line agree on how many steps there are (#902) (2c801e0)

0.0.1-alpha.168 (2026-08-16)

Bug Fixes

  • compat: a grouped sum lands on the dimension it declares (#900) (f104206), closes #756

0.0.1-alpha.167 (2026-08-16)

Bug Fixes

  • typeset: a description sets as text, not as markup (#883) (b7f383b)

0.0.1-alpha.166 (2026-08-16)

Documentation

  • nav: the gallery section says it holds examples (#890) (a4bf53b)

0.0.1-alpha.165 (2026-08-16)

Refactoring

  • gallery: a description is written when it says something (#889) (2792313)

0.0.1-alpha.164 (2026-08-16)

Features

  • language: a dimension takes its labels from an index, never from the data (#884) (13aa444)
  • language: a window's width is a column, not a run of shifts (#871) (7a90400)
  • language: an offset that differs per entity is a column, not a literal (#862) (7a3ba7b)

Bug Fixes

  • packaging: the linopy extra installs a linopy that speaks v1 (#880) (69d95ff)

Documentation

  • language: the data contract says what binding refuses and what it cannot see (#881) (24926f8)

0.0.1-alpha.163 (2026-08-16)

Bug Fixes

  • compat: a dimension index is a table on both lanes, and a defect in one reads the same (#877) (cb7af0a)

0.0.1-alpha.162 (2026-08-16)

Bug Fixes

  • bench: the floor reads the lookup by the name the model gives it (#874) (799fa85)

0.0.1-alpha.161 (2026-08-16)

Bug Fixes

  • bench: the eager arm hands over tables the lane still reads (#872) (97ab607)

0.0.1-alpha.160 (2026-08-16)

Features

  • compat: a dimension the parameters already span needs no second declaration (#869) (cf02ffa)

0.0.1-alpha.159 (2026-08-16)

Features

  • compat: choosing the linopy lane is an import, not a different call (#864) (0a74aac)

Bug Fixes

  • compat: a construct the streaming lane refuses is refused on the linopy lane too (#865) (48ca92e)

Documentation

  • architecture: the linopy lane names its verbs instead of counting them (#866) (9f93d84)

0.0.1-alpha.158 (2026-08-16)

Refactoring

  • package: the table boundary is not the engine's, and stops living under it (#860) (a5fc98f)

0.0.1-alpha.157 (2026-08-16)

Features

  • language: a file with no objective is a feasibility problem (#859) (6ddfb5b)

0.0.1-alpha.156 (2026-08-16)

Features

  • api: a parameter may be written out in Python, not only handed over as a table (#853) (b8cf21f)
  • compat: the linopy lane reads every table the product path reads (#857) (c39bd5d)

Refactoring

  • compat: the linopy lane constructs a model, it does not attach to one (#846) (e268b0b)

0.0.1-alpha.155 (2026-08-16)

Features

  • api: both lanes read the same tables, and neither reads a dense array (#855) (4afc9a7)

Documentation

  • ceiling: data prep computes what the compiler cannot derive (#854) (add8c3d)

0.0.1-alpha.154 (2026-08-16)

Bug Fixes

  • typeset: a boolean mask says which rows are true, not which exist (#848) (85feab0)

Documentation

  • ledger: a per-generator minimum up time is sayable (#844) (0cc51da)

0.0.1-alpha.153 (2026-08-16)

Documentation

  • the reference speaks to a caller, and the internals sit under about (#831) (a105582)

0.0.1-alpha.152 (2026-08-16)

Documentation

  • ports: a claim is checked against the instance before a file is written (#841) (7a40f1b)

0.0.1-alpha.151 (2026-08-16)

Features

  • language: a small relation is declared, not supplied (#771) (3be93de)
  • language: a where reads a lookup (#768) (ab584f2)

Bug Fixes

  • language: a declared lookup map holds labels of the declared dtype (#781) (5ec2c2f)
  • language: two lookups are comparable only where their labels are (#780) (b2e2742)

0.0.1-alpha.150 (2026-08-16)

Bug Fixes

  • typeset: every operator renders, and SPEC §7 proves it (#837) (6454f72)

0.0.1-alpha.149 (2026-08-16)

Features

  • gallery: a model proves every many-to-many shape load-bearing (#747) (bb75a1a)
  • language: a coordinate is a named top-level lookup (#742) (a326026)
  • language: a lookup addresses itself, and the sibling kwarg is gone (#759) (01c243c)

Bug Fixes

  • typeset: the pullback test states its coordinate as a lookup (#835) (fb74811)

Documentation

  • gallery: a model that uses at() says so in the constructs matrix (#749) (af2a3db)

0.0.1-alpha.148 (2026-08-16)

Features

  • api: a solve says how much of the session it keeps (#815) (4cd43f5)

Bug Fixes

  • typeset: a translated index shows every operator that moved it (#830) (4c45e6b)

0.0.1-alpha.147 (2026-08-15)

Refactoring

  • bench: one comparison table, and it renders the same bytes twice (#806) (28a39fa)
  • bench: the harness stops carrying what no longer measures anything (#804) (441de0f)

0.0.1-alpha.146 (2026-08-15)

Features

  • gallery: a fuel curve is a floor per piece (#808) (c2b0ef6)

Documentation

  • gallery: every model says what it is, and so does every declaration in it (#825) (28eae9b)

0.0.1-alpha.145 (2026-08-15)

Documentation

  • gallery: the model list names every model (#819) (6a78fcc)

0.0.1-alpha.144 (2026-08-15)

Features

  • language: a declaration says what it is, and the legend reads it (#812) (6b31278)
  • language: a file says what model it is (#813) (6c081e1)
  • language: a named expression can say what it counts (#814) (d57aad1)

0.0.1-alpha.143 (2026-08-15)

Features

  • gallery: an operational life is a window read from data (#805) (7071fc0)

0.0.1-alpha.142 (2026-08-15)

Features

  • gallery: two connections may join one depot and centre (#790) (80d1949)

0.0.1-alpha.141 (2026-08-15)

Features

  • gallery: a path serves one call and crosses many arcs (#789) (640558b)

0.0.1-alpha.140 (2026-08-15)

Documentation

  • site: the notebook pages say it once (#798) (fd32ad1)

0.0.1-alpha.139 (2026-08-15)

Bug Fixes

  • bench: the floor's parity check runs again (#799) (9f240ba)

0.0.1-alpha.138 (2026-08-15)

Features

  • api: a named expression is readable after a solve (#726) (e41fbe1)
  • gallery: a generator sits on a bus and burns a carrier (#783) (5334608)
  • strategy: a sweep reads the quantity its model names (#748) (1268fb5)

0.0.1-alpha.137 (2026-08-15)

Documentation

  • examples: a notebook changes a model without a modelling API (#788) (50dd21f)

0.0.1-alpha.136 (2026-08-15)

Features

  • api: a solve says what it started from, and can be forced cold (#728) (dcf760e)

0.0.1-alpha.135 (2026-08-15)

Documentation

  • agents: a bug fix has to prove the bug was there (#784) (5de3b49)

0.0.1-alpha.134 (2026-08-15)

Bug Fixes

  • tests: the harness reads a model through the product's loader (#778) (bf9e8f6)

0.0.1-alpha.133 (2026-08-14)

Bug Fixes

  • bench: a second benchmark refuses to share the machine (#723) (f92d676)

0.0.1-alpha.132 (2026-08-14)

Refactoring

  • language: the code spells the builtins the way the docs do (#754) (799c98b)

0.0.1-alpha.131 (2026-08-14)

Bug Fixes

  • typeset: a symbol table says which notation it is written in (#740) (9e392ab)

0.0.1-alpha.130 (2026-08-14)

Documentation

  • examples: the corpus still spells what the language replaced (#739) (98ba17c)

0.0.1-alpha.129 (2026-08-14)

Features

  • language: a variable declares its domain, not a pair of flags (#720) (690cba1)

0.0.1-alpha.128 (2026-08-14)

Features

  • api: a slow build says where the time went (#717) (bab22b0)
  • api: a solved constraint row says its activity (#716) (63205d4)

0.0.1-alpha.127 (2026-08-14)

Documentation

  • the builtins have one name and a derived dimension states its cost (#715) (916cd8d)

0.0.1-alpha.126 (2026-08-14)

Bug Fixes

  • engine: a coordinate may target a dimension nothing spans yet (#714) (f93969e)
  • tests: the coordinate-target fixture speaks the current objective surface (#734) (5d18833)

0.0.1-alpha.125 (2026-08-14)

Features

  • language: a second objective is unsayable, not caught (#729) (6c9d986)

0.0.1-alpha.124 (2026-08-14)

Documentation

  • design: the ceiling's indicator row names its live issue (#712) (81facb4)

0.0.1-alpha.123 (2026-08-14)

Performance

  • engine: a coefficient of zero stops reaching the solver (#685) (6a6c026)
  • engine: a share stops carrying its zeros through the sort (#686) (ca7b54e)

Documentation

  • spec: the indicator and lp rows cite the issues that hold them (#696) (2aa70c9)

0.0.1-alpha.122 (2026-08-14)

Features

  • api: diagnostics say what the sink added to the model it was handed (#689) (0e6c75a)
  • language: a piecewise curve may name its formulation (#688) (d420c8b)
  • language: a variable may declare a special-ordered set over one of its dims (#687) (94cc18e)

Performance

  • engine: a set costs a fraction of the variable it is declared over (#691) (413d493)

0.0.1-alpha.121 (2026-08-13)

Documentation

  • models: both tabs start from the same tables (#678) (dc50136)
  • models: every teaching model is verified and reads in linopy (#680) (613a8e8)
  • models: the journey from files to the shared tables has one page (#679) (bdc636d)
  • models: the linopy tabs read as linopy users write, types said where hidden (#681) (840e79e)
  • models: the model files speak as a modeller, the pages teach the language (#682) (07c58b4)

0.0.1-alpha.120 (2026-08-13)

Documentation

  • models: the gallery shows the modelling, not the harness (#673) (6adba43)

0.0.1-alpha.119 (2026-08-13)

Refactoring

  • dead code, one-entry registries and re-export shims are gone (#675) (a1f61df)

0.0.1-alpha.118 (2026-08-13)

Refactoring

  • a value crossing a module boundary names its fields (#667) (51b5249)

0.0.1-alpha.117 (2026-08-13)

Documentation

  • models: the teaching models are verified, read in linopy, and show their call (#671) (83ab265)

0.0.1-alpha.116 (2026-08-13)

Documentation

  • models: each verified reference reads as a tab beside the model (#665) (9497594)

0.0.1-alpha.115 (2026-08-13)

Documentation

  • agents: a guard nobody can delete unseen is the coverage bar (#662) (4b90f6e)

0.0.1-alpha.114 (2026-08-13)

Features

  • api: a built model takes new numbers without being rebuilt (#626) (5123215)

Performance

  • strategy: a serial sweep binds one model instead of building each slice (#627) (cfdcc95)

0.0.1-alpha.113 (2026-08-13)

Documentation

  • agents: AGENTS.md scans as rules rather than paragraphs (#657) (f5bba8e)

0.0.1-alpha.112 (2026-08-13)

Performance

  • engine: a solver reads the row vectors instead of scattering them (#651) (ba1587d)

0.0.1-alpha.111 (2026-08-13)

Performance

  • engine: constants stop doubling the cost of a constraint's rows (#650) (a89a2c9)
  • sinks: a row's comparison crosses to the solver as a code, not a string (#648) (b0bb8c3)
  • sinks: the solver's column vectors stop being walked five times (#649) (98d604d)

0.0.1-alpha.110 (2026-08-12)

Bug Fixes

  • engine: a variable and a constraint may share a name (#645) (e4329cf)

0.0.1-alpha.109 (2026-08-12)

Documentation

  • agents: the package's docstrings have one checkable form (#632) (bdc301f)

0.0.1-alpha.108 (2026-08-12)

Documentation

  • agents: what is non-negotiable, and what is a default you may argue with (#624) (526c11a)

0.0.1-alpha.107 (2026-08-12)

Refactoring

  • every claim lives where it is read, not in a comment (#612) (a5404d7)

0.0.1-alpha.106 (2026-08-12)

Bug Fixes

  • bench: the marginal-cost caption is rendered, and says what it measures (#621) (93cd5fe)

0.0.1-alpha.105 (2026-08-12)

Documentation

  • agents: a number leaves only with a pointer, and vagueness is not a conclusion (#618) (5489607)

0.0.1-alpha.104 (2026-08-12)

Documentation

  • agents: a PR with no intent line shows the prompt that produced it (#616) (aa134ab)

0.0.1-alpha.103 (2026-08-11)

Performance

  • examples: the benders loop parses each model once (#613) (5f03dbd)

0.0.1-alpha.102 (2026-08-11)

Features

  • strategy: one model solved over scenarios, windows and pathways (#459) (5d4c4ce)

0.0.1-alpha.101 (2026-08-11)

Documentation

  • agents: a claim belongs in the message that prints (#608) (d0b1e86)

0.0.1-alpha.100 (2026-08-11)

Documentation

  • agents: a reader can tell the maintainer's voice from an agent's (#605) (b987971)

0.0.1-alpha.99 (2026-08-11)

Documentation

  • AGENTS.md carries how we work, CLAUDE.md just imports it (#599) (e815252)

0.0.1-alpha.98 (2026-08-11)

Documentation

  • the copyright line names whoever wrote it, and that was never PyPSA (#601) (06fb7d5)

0.0.1-alpha.97 (2026-08-11)

Documentation

  • the surface is Calliope's, the vocabulary is linopy's — say so (#598) (a1042fc)

0.0.1-alpha.96 (2026-08-11)

Refactoring

Documentation

  • design: decomposition, as evidence rather than as a feature (#597) (c736da9)

0.0.1-alpha.95 (2026-08-11)

Bug Fixes

  • engine: a returned frame speaks String, so it joins the caller's own (#593) (69b9ad2)

0.0.1-alpha.94 (2026-08-11)

Refactoring

0.0.1-alpha.93 (2026-08-11)

Bug Fixes

  • api: a closed result says it was closed (#587) (45cc1d0)

0.0.1-alpha.92 (2026-08-11)

Bug Fixes

  • data: an empty index keeps the dimension's declared dtype (#585) (b5bd409)

0.0.1-alpha.91 (2026-08-11)

Performance

  • engine: the objective keeps the hash count — bought order was a shape-dependent bet (#581) (d30598f)

0.0.1-alpha.90 (2026-08-11)

Refactoring

  • engine: ask the data, not the declarations (#520) (17f8e5d)

0.0.1-alpha.89 (2026-08-11)

Bug Fixes

  • plan: a divisor under a pullback is still named (#571) (2591995)

0.0.1-alpha.88 (2026-08-11)

Performance

  • engine: the bound attach reads the ordinal off the Enum, not a dictionary (#568) (6847419)

0.0.1-alpha.87 (2026-08-11)

Performance

  • engine: a bound dense over the variable product is attached, not joined (#511) (8efd207)

0.0.1-alpha.86 (2026-08-11)

Features

  • language: a coordinate may declare its own label space (#557) (220fd8a)
  • language: a row with no variable terms is not built, and is reported (#561) (4cf2ea5), closes #556

0.0.1-alpha.85 (2026-08-10)

Performance

  • engine: the matrix stops repeating itself — CSR at assembly (#550) (903c8c2)

0.0.1-alpha.84 (2026-08-10)

Features

0.0.1-alpha.83 (2026-08-10)

Bug Fixes

  • engine: a zero edge writes its rows, like every other fill (#551) (af1ce64)

0.0.1-alpha.82 (2026-08-10)

Bug Fixes

  • engine: a nested shift keeps its presence's own dims (#546) (c7cb8a0), closes #544

0.0.1-alpha.81 (2026-08-10)

Bug Fixes

  • language: the bare-shift refusal names a pair, not three alternatives (#540) (96bbbaa)

Performance

  • engine: a string dimension speaks its own Enum, everywhere at once (#541) (8517945)

0.0.1-alpha.80 (2026-08-10)

Bug Fixes

  • api: one exception tree, whichever door built the model (#538) (52cdb8b), closes #527
  • linopy: extend() passes the borrowed names to its own expansion (#542) (282a2d3)

0.0.1-alpha.79 (2026-08-10)

Bug Fixes

  • language: a Model validates itself, however it was built (#533) (6b987a6)

0.0.1-alpha.78 (2026-08-10)

Refactoring

  • api: Model, and a model that can be written back out (#522) (ccefd98)

0.0.1-alpha.77 (2026-08-09)

Documentation

  • lp: the presort's cost is unmeasured, not settled (#517) (5ca09f0)

0.0.1-alpha.76 (2026-08-09)

Features

  • language: version: on a model file, and 0 means unstable (#515) (7d37589)

0.0.1-alpha.75 (2026-08-09)

Refactoring

  • language: edge takes a quoted keyword, edge='wrap' (#512) (d20d44e)

0.0.1-alpha.74 (2026-08-09)

Documentation

  • roll is not a spelling — shift(edge=wrap) is (#509) (6f1f98a)

0.0.1-alpha.73 (2026-08-09)

Performance

  • lp: the constraint stream sorts on one key, carrying nothing else (#492) (e7085ca)

0.0.1-alpha.72 (2026-08-09)

Bug Fixes

  • docs: install uv on Read the Docs without asdf (#501) (13e095e)

0.0.1-alpha.71 (2026-08-09)

Refactoring

  • language: group_sum becomes sum(group_by=) (#491) (fb14dd2)

0.0.1-alpha.70 (2026-08-09)

Features

  • language: at() — the pullback of group_sum (#489) (e7ce036)

Performance

  • polars: two group_sums collide only where the coordinates meet, and the matrix leaves in row order (#487) (53621b1)

0.0.1-alpha.69 (2026-08-09)

Bug Fixes

  • language: quoted literals in a where, and a dtype guard on comparisons (#485) (968861b)

0.0.1-alpha.68 (2026-08-09)

Documentation

  • cli: the typeset shell front is not a command line under construction (#483) (72b8ced)

0.0.1-alpha.67 (2026-08-09)

Bug Fixes

  • engine: a masked-out scalar variable takes its row with it (#480) (2e6f329)

0.0.1-alpha.66 (2026-08-09)

Documentation

  • roadmap: motivation and end state; the detail moves to issues (#474) (ebff8b0)

0.0.1-alpha.65 (2026-08-09)

Documentation

  • contributing: issues cite behaviour, and two labels carry order (#466) (86398fd)

0.0.1-alpha.64 (2026-08-09)

Documentation

  • models: monthly_budget — group_sum over time, not just space (#461) (ab8d71f)

0.0.1-alpha.63 (2026-08-09)

Documentation

  • api: Gurobi Compute Server, Instant Cloud and WLS already work (#458) (4f18e89)

0.0.1-alpha.62 (2026-08-01)

Documentation

  • bench: plot the results, and fold the tables under them (#451) (042c2ad)

0.0.1-alpha.61 (2026-07-31)

Bug Fixes

  • bench: the default arm clears the engine it did not select (#452) (6e4e3a3)

0.0.1-alpha.60 (2026-07-31)

Refactoring

  • bench: the harness is pytest; drop the custom runner (#448) (d460ca6)

0.0.1-alpha.59 (2026-07-31)

Performance

  • engine: the read-back reads the label order rather than re-imposing it (#446) (53f8eb8)

0.0.1-alpha.58 (2026-07-31)

Documentation

  • bench: re-measure at 98f382d, and correct a claim the harness bug made (#441) (6d0e195)

0.0.1-alpha.57 (2026-07-31)

Performance

  • sinks: a solution is a vector, not a vector beside its own index (#439) (76600ab)

0.0.1-alpha.56 (2026-07-31)

Bug Fixes

  • bench: compare like with like, and add a gurobi arm (#438) (ea15cb4)

0.0.1-alpha.55 (2026-07-31)

Performance

  • engine: cols is positional, and the order is produced rather than repaired (#433) (22bb9c7)

0.0.1-alpha.54 (2026-07-31)

Performance

  • sinks: a row is seated the way a column is, for both solvers (#421) (31ba48c)

0.0.1-alpha.53 (2026-07-31)

Performance

  • gurobi: hand the matrix over in one call (#434) (3d13d50)

0.0.1-alpha.52 (2026-07-31)

Features

  • sinks: gurobi, and the two families it revealed (#418) (8730498)

0.0.1-alpha.51 (2026-07-31)

Documentation

  • breaking changes are free while we are 0.0.1aN (#420) (ae1389a)

0.0.1-alpha.50 (2026-07-31)

Performance

  • polars: a constraint over distinct variables has nothing to collapse (#408) (8e725de)
  • polars: a fragment is not restricted by its own absence (#413) (8ac3a0d)
  • polars: a mask joins for what it is certain of (#415) (68d95e2)
  • polars: a solve is read back by position, not by key (#414) (cba01c4)
  • polars: an existence join does not deduplicate what it asks about (#412) (c008154)

0.0.1-alpha.49 (2026-07-31)

Bug Fixes

  • bench: the build profiler names steps that still exist (#406) (e771686)

0.0.1-alpha.48 (2026-07-31)

Bug Fixes

  • bench: the regression harness builds again (#400) (291f714)

0.0.1-alpha.47 (2026-07-31)

Refactoring

  • relational: the contract at the top, engines one level down (#395) (fb4b2de)

0.0.1-alpha.46 (2026-07-31)

Features

  • rename LinopyYamlError to LpspecError (#394) (5f72731)

0.0.1-alpha.45 (2026-07-31)

Documentation

  • quadratic is planned, not refused — and the ceiling is relational ∩ local (#388) (2a8c172)

0.0.1-alpha.44 (2026-07-31)

Documentation

  • fix five stale claims, and cut what git already remembers (#386) (6562c15)

0.0.1-alpha.43 (2026-07-31)

Documentation

  • ceiling: the plan cannot loop, the process can — scope the refusal (#378) (55d238c)

0.0.1-alpha.42 (2026-07-31)

Documentation

  • architecture: the consumers diagram carries the shape, not the list (#377) (fb06b82)

0.0.1-alpha.41 (2026-07-31)

Documentation

  • architecture: show the public surface, and pin it (#375) (bdb6b11)

0.0.1-alpha.40 (2026-07-31)

Refactoring

  • architecture: four directories, four enforced fences (#373) (f5e2c09)

0.0.1-alpha.39 (2026-07-31)

Refactoring

  • language: the front end is a package, and degree 1 lives in it (#371) (0bcfd1b)
  • relational: binding produces a value, and the live registry is visibly the exception (#370) (70e13ba)

0.0.1-alpha.38 (2026-07-31)

Refactoring

  • relational: labels and the result are modules, not regions of the executor (#368) (7c8604a)
  • three small simplifications in the eager lane and piecewise (#366) (b8a5d3e)

0.0.1-alpha.37 (2026-07-31)

Documentation

  • architecture: the CLI ships, and the typeset spike is a package (#363) (f0b6cf1)

0.0.1-alpha.36 (2026-07-31)

Refactoring

  • one near-miss clause, one fold, and comments that restate their line (#361) (48464fc)

0.0.1-alpha.35 (2026-07-31)

Features

  • language: one shift(along=, offset=, edge=), replacing roll and shift (#359) (8473a24)

0.0.1-alpha.34 (2026-07-30)

Performance

  • relational: coordinate validation rides the aggregate already running (#357) (093a694), closes #273

0.0.1-alpha.33 (2026-07-30)

Refactoring

  • relational: one data-validation module for this lane (#355) (4b19fe4)

0.0.1-alpha.32 (2026-07-30)

Bug Fixes

  • relational: refuse a source label the dimension does not have (#352) (5600cd8), closes #350

0.0.1-alpha.31 (2026-07-30)

Bug Fixes

  • relational: a mask survives a broadcast into a reduction (#348) (3515fd6)

0.0.1-alpha.30 (2026-07-30)

Bug Fixes

  • bench: migrate the bench corpus off equations:, and gate it (#346) (72818b2), closes #343

0.0.1-alpha.29 (2026-07-30)

Documentation

  • the corpus teaches shift for the acyclic boundary, and names what repeats (#342) (586daa3)

0.0.1-alpha.28 (2026-07-30)

Bug Fixes

  • relational: the empty coordinate — scalar rows, columns and values (#339) (15c2892)

0.0.1-alpha.27 (2026-07-30)

Refactoring

  • rename the package to lpspec, drop the farkas branding (#336) (0dd27d4)

0.0.1-alpha.26 (2026-07-30)

Bug Fixes

  • parser: the inf literal needs a word boundary (#335) (c34bf1a), closes #302

0.0.1-alpha.25 (2026-07-30)

Documentation

  • the ten laws at the head of SPEC, one evidence page, the ceiling as its own note (#333) (71ae5f7)

0.0.1-alpha.24 (2026-07-29)

Features

  • one rule per constraint, named by the file rather than by position (#329) (1ff53b3)

0.0.1-alpha.23 (2026-07-29)

Bug Fixes

  • api: read-back by an unknown name says what the model actually built (#327) (018b1ff)

0.0.1-alpha.22 (2026-07-29)

Documentation

  • spec: when a fill belongs in the language, and when it is data prep (#325) (5f71da8)

0.0.1-alpha.21 (2026-07-29)

Documentation

  • the home page shows the model it sets, as math (#317) (4094fb9)
  • typeset: say that symbols= takes a dict, not only a path (#323) (e9f2102)

0.0.1-alpha.20 (2026-07-29)

Bug Fixes

  • linopy: refuse a missing bound at build, with the native lane's message (#319) (0e75754)

0.0.1-alpha.19 (2026-07-29)

Bug Fixes

  • a divisor must be defined where the model divides by it (#318) (d7ad809)
  • relational: absence propagates into a reduction, and laws to hold it there (#314) (f4bb63b)

0.0.1-alpha.18 (2026-07-29)

Documentation

  • typeset every model page from the model it shows (#280) (d6eda33)

0.0.1-alpha.17 (2026-07-29)

Features

  • typeset a validated model — LaTeX and Typst (spike) (#269) (3cbd79a)

Bug Fixes

  • ci: the PR-title check must report on every head, or it blocks the merge (#308) (ecbdb13)

0.0.1-alpha.16 (2026-07-29)

Documentation

  • releasing: the alpha stream is 0.0.1, and say what actually holds it (#306) (de597a6)

0.0.1-alpha.15 (2026-07-29)

Bug Fixes

  • ci: check out the manifest the version guard reads (#303) (911b9ed)

0.0.1-alpha.14 (2026-07-29)

Documentation

  • models: fold long expressions onto one term per line (#299) (826eaaa)

0.0.1-alpha.13 (2026-07-29)

⚠ BREAKING CHANGES

  • linopy: importing farkas.linopy sets linopy.options['semantics'] to 'v1' process-wide. Models built through this lane change answer wherever a variable is masked or shifted — that is the point, and it is the answer the native engine has always given.
  • a bare shift() now drops the row at the vacated coordinate instead of contributing zero there, and shift() over a variable-free expression is a load error. Add fill=0 for the previous behaviour.

Features

  • shift() creates absence, as linopy v1 says it does (#291) (b394e70)

Bug Fixes

  • linopy: the lane selects v1 on import, and fill= takes the identity of its position (#293) (451c354)
  • release: put the version back on the alpha stream, and make the pin real (#295) (8ef60a5)

0.0.1-alpha.12 (2026-07-29)

Documentation

  • spec: three behaviours a consumer could only reach by probing (#288) (50b087c)

0.0.1-alpha.11 (2026-07-29)

Bug Fixes

  • docs: readable mermaid diagrams in dark mode, and the site icons (#285) (b21d5d8)

0.0.1-alpha.10 (2026-07-28)

Documentation

  • publish the site with mkdocs-material (#283) (1ec55ac)

0.0.1-alpha.9 (2026-07-28)

Bug Fixes

  • result: read the solution back in label order (#278) (11bf86d)

0.0.1-alpha.8 (2026-07-28)

Bug Fixes

  • piecewise: emit foreach in declaration order, not set order (#271) (c06907b)
  • where: a declared dimension on a comparison RHS is a load error (#272) (5b1784e)

0.0.1-alpha.7 (2026-07-28)

Documentation

  • the AST as a narrow waist — one contract, many consumers (#266) (688c6df)

0.0.1-alpha.6 (2026-07-28)

Documentation

  • say what examples/ is, and point it at the explained version (#263) (aab7617)

0.0.1-alpha.5 (2026-07-28)

Documentation

  • move the three root docs, add a guide, make the index a path (#260) (bfbfbec)

0.0.1-alpha.4 (2026-07-28)

Documentation

  • a model gallery, with a construct matrix read off the plan (#257) (e9cf410)

0.0.1-alpha.3 (2026-07-28)

Documentation

  • a CONTRIBUTING.md, and move procedure out of the corpus page (#255) (d3d5f96)

0.0.1-alpha.2 (2026-07-28)

Refactoring

  • bench: retire the duckdb arm, and the docs it was holding up (#253) (6eaef1e)

0.0.1-alpha.1 (2026-07-28)

⚠ BREAKING CHANGES

  • rebuild the relational engine on polars (#189)

Features

  • rebuild the relational engine on polars (#189) (c11a0dd)

Chores

  • re-cut as 0.0.1-alpha.1, and refresh the chart page from the results (#250) (f62d434)

0.0.0-alpha.33 (2026-07-28)

⚠ BREAKING CHANGES

  • absence propagates and drops the row, plus defined(v) (#239)

Features

  • absence propagates and drops the row, plus defined(v) (#239) (5eb5943)

0.0.0-alpha.32 (2026-07-28)

Features

  • compat: answer linopy's v1 convention where the position knows the answer (#236) (facee3f), closes #8

0.0.0-alpha.31 (2026-07-28)

Documentation

  • alpha.30 credited a perf fix it does not contain (#230) (5afb004)

0.0.0-alpha.30 (2026-07-28)

Documentation

  • pin all three label paths, and write the row-major order down (#152) (3d8c725)

No functional change: this release is alpha.29 plus tests and a paragraph of docs/ARCHITECTURE.md. The commit subject says perf: and claims a speed-up, which is wrong — that optimisation shipped in alpha.29 as #178. #152 was retitled after it had already been merged and released, too late for the squash subject.

0.0.0-alpha.29 (2026-07-28)

Performance

  • compute variable labels arithmetically when the mask factors (#178) (5d4745f)

0.0.0-alpha.28 (2026-07-28)

Bug Fixes

  • three ways an objective or a scalar parameter answered quietly (#223) (ee08d5d)

0.0.0-alpha.27 (2026-07-28)

Bug Fixes

  • refuse a parameter source that carries a coordinate twice (#201) (fffee97)

0.0.0-alpha.26 (2026-07-27)

Documentation

  • bench: correct the label-optimisation numbers, and say how to get them (#188) (bf84fd1)

0.0.0-alpha.25 (2026-07-27)

Performance

  • sink: size the hand-off by nonzeros, under one budget and one chunking rule (#195) (c31beaf)

0.0.0-alpha.24 (2026-07-27)

Performance

  • sink: hand Arrow to numpy directly, not through to_pydict (#193) (ac64f26)

0.0.0-alpha.23 (2026-07-27)

Performance

  • skip the objective's GROUP BY where a column cannot repeat (#179) (787b1ce)

0.0.0-alpha.22 (2026-07-27)

Performance

  • lp: render doubles with ::VARCHAR instead of printf('%.17g') (#190) (b1df538)

0.0.0-alpha.21 (2026-07-27)

Performance

  • relational: a label is a position, so compute it instead of counting it (#186) (a31645b)

0.0.0-alpha.20 (2026-07-27)

Bug Fixes

  • the HiGHS sink's column ingest was an unbounded global sort (#181) (271b0d7)

0.0.0-alpha.19 (2026-07-27)

Features

  • expose duals on the solve path (sol.dual) (#156) (284df79)

0.0.0-alpha.18 (2026-07-27)

Features

  • bench: a performance harness the published numbers come from (#143) (144713a)

0.0.0-alpha.17 (2026-07-27)

Features

  • forward solver_options, and gate reads on an actual incumbent (#169) (493a5e6)

0.0.0-alpha.16 (2026-07-27)

Documentation

  • the memory invariant says what it actually guarantees (#150) (8ffe339)

0.0.0-alpha.15 (2026-07-27)

⚠ BREAKING CHANGES

  • documentation only — the suggested alias is now fk. import farkas was and remains the actual import.

Chores

  • the import alias is fk, because the package is farkas (#154) (fac76f0)

0.0.0-alpha.14 (2026-07-27)

⚠ BREAKING CHANGES

  • Solution is now Result; status returns the coarse axis (ok) rather than the solver's wording (Optimal) — termination_condition carries that, and is_ok is what most call sites meant. objective is nan and primal/to_* raise NoSolutionError when the solve produced nothing.

Features

  • a solve result tells you whether it has one (#148) (30a91c8)

0.0.0-alpha.13 (2026-07-26)

Bug Fixes

0.0.0-alpha.12 (2026-07-26)

Bug Fixes

  • a null coordinate means "no group", not a typo (#135) (9a672b4)

0.0.0-alpha.11 (2026-07-26)

Documentation

  • lead with what the package is; YAML is the format we ship, not the interface (#132) (5bd5240)

0.0.0-alpha.10 (2026-07-26)

Bug Fixes

  • py.typed ships with the package it describes (#131) (52529de)

0.0.0-alpha.9 (2026-07-26)

⚠ BREAKING CHANGES

  • the import path is now farkas; the compat lane is farkas.linopy and its extra is [linopy].

Refactoring

  • rename the package to farkas, and compat/ to linopy/ (#127) (5fae345)

0.0.0-alpha.8 (2026-07-26)

Refactoring

  • one lazy import left, and it is the only real cycle (#117) (ecad711)

0.0.0-alpha.7 (2026-07-26)

Refactoring

  • the package moves under src/, so CI tests the artifact (#118) (7eb39a6)

0.0.0-alpha.6 (2026-07-26)

Features

  • accept any Arrow-compatible table as a source (#104) (e8a699e)

Refactoring

  • three modules in the engine, one per box in the diagram (#107) (f6b30b2)

Documentation

  • the seam's level is decided, so stop pointing at an open issue (#111) (7d1a992)

0.0.0-alpha.5 (2026-07-26)

⚠ BREAKING CHANGES

  • a file declaring more than one objective no longer loads.
  • a Series or DataArray whose index names are not the declared dims is now a DataError; previously the names were discarded.
  • a dimension declares the coordinates its labels carry (#100)
  • every IR, AST and schema class is renamed, and fk.LanguageError no longer covers data-binding failures — those are fk.DataError. Both remain under fk.LinopyYamlError, as does the deprecated RelationalBuildError alias.

Features

  • a dimension declares the coordinates its labels carry (#100) (49b790b)

Bug Fixes

  • a bool parameter is a mask, on both lanes (#47) (#96) (a3f3926)
  • a declared coordinate must be its declared dtype (#65) (#101) (5349991)
  • a named index binds by name, not by position (#91) (#98) (3e14be8)
  • a second objective is a load error, not a silent drop (#49) (#97) (24f5849)
  • one place per language rule, and formulations judged like the rest (#99) (3137fbc)

Refactoring

  • names say what they mean, and errors are one tree (#94) (0c1300c)
  • the compat lane is a directory, so the fence is structural (#95) (4015131)

Documentation

  • consolidate the doc set and cut it by two thirds (#87) (0a89d7d)
  • runnable architecture walkthrough, one stage at a time (#54) (0f0910f)
  • say plainly that breaking changes land without a deprecation cycle (#102) (6131342)
  • split sink capability from the expressive ceiling (#88) (4e58227)
  • the composition seam exists, and value-only re-solve has a precondition (#93) (2dffd89)

0.0.0-alpha.4 (2026-07-25)

⚠ BREAKING CHANGES

  • unknown YAML keys are an error, not a silent default (#72)
  • sum/roll/shift/group_sum over a dim the operand does not carry, a where dim outside the frame, a bound parameter dim outside foreach, and a constraint whose expression dims differ from its foreach are all load errors. Each previously built a model that solved and was wrong, or larger than the file read as.

Features

  • Result.to_xarray() — the labelled form, one call away (#75) (7df73b4)
  • static dim checking — the type is a set of dim names (#68) (f96bcb4)

Bug Fixes

  • dim checking runs on both lanes, and binary ops union (#70) (2072cfa)
  • read YAML 1.2 booleans, and refuse duplicate keys (#77) (b12af91)
  • unknown YAML keys are an error, not a silent default (#72) (909bc4c)

Documentation

  • an objective totals its dims, so the examples stop pretending otherwise (#74) (f090c8c)
  • the axes the expressiveness taxonomy does not rank (#76) (bcfcdee)

0.0.0-alpha.3 (2026-07-25)

⚠ BREAKING CHANGES

  • where: "<dimension>" is a load error. It never did anything except in the case where it broke.
  • an unknown name in a where string is a load error rather than a False mask; parameter-vs-parameter where comparisons are rejected; and names may no longer collide across kinds. Each was a way to build a model that solved and was silently wrong.
  • a variable declared without bounds.lower was silently non-negative; it is now unbounded below, matching linopy's add_variables(lower=-inf). Models relying on the implicit >= 0 must write lower: 0. An LP that was bounded only by that implicit constraint will now report as unbounded.

Bug Fixes

  • a bare dimension name in a where is a load error (#64) (1a89fef)
  • both lanes agree on where-comparisons over dimensions, and on ** (#52) (7bec431)
  • check() enforces degree 1; README stops promising a fallback (#55) (d0b008c)

Refactoring

  • cut back the accumulated surface (#56) (1802dd0)
  • finish the lane split — where_parser keeps grammar, not evaluation (#59) (a30f7ec)
  • let the annotations say what the parsers already guarantee (#61) (49387d4)
  • name resolution is a pass, not a backend detail (#62) (8622fa6)

Documentation

  • cross-language vocabulary map, and a procedure for the ceiling (#63) (7f535cd)
  • SPEC catches up with the code it describes (#57) (50edfb6)

0.0.0-alpha.2 (2026-07-24)

Bug Fixes

  • name-check dimension kwargs at load time; restore docs lost at merge (#48) (4c6bfc9)

0.0.0-alpha.1 (2026-07-24)

Features

  • API polish — check(), write(), LanguageError, Result lifecycle (#36) (fc36af5)