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.2.1 (2026-09-29)

This release fixes three wrong answers. None of them raised an error. A model that meets one builds a different row, or reads a different value, in 0.2.1. No file, archive or import breaks.

  • A sum over a variable with a where:, beside a parameter over fewer dimensions, such as sum(y + w, over=f) with w over f alone. The parameter now drops out where the variable is absent, in the constraint row and in evaluate. Before, it stayed in, so the row had a wrong right-hand side.
  • A divisor, a power's base or an exponent that is a sum(...). It is now taken as its total, in a build and in a read. Before, it was taken summand by summand.
  • A reported quotient whose divisor is absent or zero. It now has no value at that coordinate. Before, it read inf or raised a DataError.

Result.dual now states the sign of a dual: the rate at which the optimal objective rises with the row's right side, for every comparator, under either sense and on every solver. No value changes. mathspec's reference now defines dual(c) the same way (energy-models/mathspec#751).

The pull requests since 0.2.0:

  • fix(engine): a sum leaves out a parameter where a variable added to it is absent, in the model and in a read (#1784)
  • fix(engine): a divisor, a power's base or an exponent that is a sum is taken as its total rather than summand by summand (#1779)
  • fix(api): a reported quotient is absent where its divisor is absent or zero (#1776)
  • docs(api): a dual is the rate at which the optimal objective rises with its row's right side, on every sink (#1774)

0.2.0 (2026-09-25)

A saved answer now records which layout it was written in and which specsolve wrote it, so a later release can name an answer it no longer reads. The Python API reference is now rendered from the docstrings.

This release breaks one thing:

  • An answer or an archive that 0.1.0 or earlier wrote is refused with a LayoutError that says to solve the model again and save it. Its format.json reads {"answer": 0}; 0.2.0 writes {"layout": 1, "specsolve": "0.2.0"}. An archive still holds the spec and the data it was solved with, under spec.yaml and sources/.

The pull requests since 0.1.0:

  • feat(api)!: a saved answer is stamped with layout 1 and the specsolve version that wrote it, and one written by 0.1.0 or earlier is refused by name (#1765)
  • docs: each fact about the Python API is stated once, in the docstring of the name it belongs to (#1769)
  • docs: the Python API page renders every public name from its docstring (#1766)
  • docs(sweeps): the sweep reference says how many sessions a sweep opens on a remote Gurobi (#1771)

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)