NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #3216 most downloaded on pub.dev
A framework-agnostic Seed/Branch keyed-reconcile tree engine — Flutter's element/reconciliation model extracted to pure, bare-VM Dart.
Last release 3 days ago
05 Oct 2026
Ships fairly regularly
a new release about every 2 weeks
Nearly every release is documented
notes for 11 of 11 stable releases
Nothing withdrawn
no release was ever pulled
3 months old
14 releases · first in 2026
One column per month.
feat(tree)!: watch/read nullability follows the type argument (genesi…
feat(tree)!: watch/read nullability follows the type argument (genesi…
chore(release): genesis dev wave - genesis_tree 0.5.0-dev.1 (Element/…
chore(release): genesis dev wave - genesis_tree 0.5.0-dev.1 (Element/…
chore(release): genesis_tree 0.4.0 — stable promotion of 0.4.0-dev.1 …
chore(release): genesis_tree 0.4.0 — stable promotion of 0.4.0-dev.1 …
Stable promotion of 0.4.0-dev.1: the same content, published on the stable rung on Nico's promotion call (2026-09-12). The wave is additive over 0.3.1; the 0.4.0-dev.1 entry below carries the full list.
The 0.4.0 wave ( #22 , #24 , #26 , #27 , #28 , #33 ) was authored as a stable 0.4.0 whose tag publish failed on 2026-09-10 (pub.dev bearer 403, dart-l
The 0.4.0 wave (#22, #24, #26, #27, #28, #33) was authored as a stable
0.4.0 whose tag publish failed on 2026-09-10 (pub.dev bearer 403,
dart-lang/pub-dev#9576); the version never reached pub.dev and four more
PRs have since landed into it. Both release nodes were retargeted to a
prerelease on the pow-m4na ruling, so this cuts the wave as
0.4.0-dev.1: classify reads the wave as additive over 0.3.1 (18 public
API additions, none breaking), the CHANGELOG entry leads with that, and
every workspace consumer of genesis_tree moves from ^0.4.0 to
^0.4.0-dev.1 so local resolution stays valid and later 0.4.0 rcs and the
stable still satisfy it.
Refs: genesis-v43, genesis-mg0
Co-authored-by: Claude Fable 5.1 noreply@anthropic.com
Prerelease on the dev rung: this wave is additive over 0.3.1 (nothing published in 0.3.1 is removed or changed) and its API is still moving; stable 0.4.0 is a separate, human-promoted act.
Provider, ProviderScope, ProviderTreeContext, AvailabilityRegistry, LifecycleProvider) and their contract suite, lifted out of grid_engine's private sources and exported publicly. The provider kind-swap check is an independent StateError in every build mode.TreeLifecyclePhase, TreeLifecyclePhaseGuard, TreeOwner.lifecyclePhaseGuard): one lifecycle phase definition for tree drivers, composed with the owner flush marker; retained-context dependency registration before mutation is rejected.ProxyProvider through ProxyProvider6): one- through six-input proxy providers that derive owned ambient values through the existing provider lifecycle and availability registry, sharing replacement and teardown ownership across providers.TreeLifecycleParticipant, TreeSnapshotReader, TreeWatchingReader): call-scoped snapshot and watching readers driven through the shared phase guard, with mounted identity retained across reconciliation; only participants the provider constructed are disposed. Retained reader use and invalid in-place participant replacement fail loudly in every build mode.TreeDependencyScope): TreeLifecycleParticipant.didChangeDependencies receives a retainable scope that becomes non-current on the next pass or on teardown, and the provider invalidates scopes before participant disposal for owned and adopted participants alike, so continuation staleness stays out of the synchronous build path.BREAKING CHANGE: Code that caught AssertionError from the re-dirty, duplicate-key, or incompatible-update guards must catch StateError. Refs: genesis-…
Make the re-dirty, duplicate-key, and incompatible-update guards throw StateError in all build modes. Dialogue surfaces now reject incompatible roots before mutation and commit metadata only after a successful update; release-mode regressions and patch metadata cover both packages.
BREAKING CHANGE: Code that caught AssertionError from the re-dirty, duplicate-key, or incompatible-update guards must catch StateError.
Refs: genesis-7ob
Co-authored-by: Nico Spencer nicholas.scott.spencer@gmail.com
StateError with the message the assertion carried. (1) TreeOwner.flush rejects a branch re-dirtied after it was already built in the pass — a branch that calls setState from inside its own build used to drain forever in release; the pass is bounded at one build per branch. (2) Branch.updateChildren rejects duplicate non-null sibling keys before it touches the old child list, so a rejected reconcile leaves the mounted tree unchanged. (3) Branch.update rejects a seed that fails canUpdate instead of swapping in an incompatible config. No API change; code that relied on catching AssertionError from these three paths now catches StateError.BREAKING CHANGE: InheritedBranch.addDependent overrides and context handle implementations must accept and forward the optional aspect parameter.
Record the aspect-scoped inherited dependency API under new minor versions and retarget every workspace consumer so local resolution stays coherent.
BREAKING CHANGE: InheritedBranch.addDependent overrides and context handle implementations must accept and forward the optional aspect parameter.
Refs: genesis-dsu
InheritedBranch.addDependent is now addDependent(Branch branch, {Object? aspect}), and dependOnInheritedSeedOfExactType<T>() gained an optional {Object? aspect} on Branch, TreeContext, and SproutContext. Migration for a subclass that overrides addDependent: add the named parameter and forward it — void addDependent(Branch branch, {Object? aspect}) => super.addDependent(branch, aspect: aspect); — which preserves the base provider's rejection of an aspect it has no vocabulary for. An external TreeContext implementation adds {Object? aspect} to its dependOnInheritedSeedOfExactType and passes it straight through to the handle it wraps. Call sites that pass no aspect are unchanged.InheritedModelSeed<T, A> and InheritedModelBranch<T, A>: an ambient value whose dependents may subscribe to a single ASPECT of it. A dependent that passes aspect: is invalidated only when updateShouldNotifyDependent reports the change as touching one of the aspects it asked for; omitting the aspect keeps the whole-value dependency InheritedSeed always gave. Lookup is unchanged — still the nearest provider of exact value-type T — so a plain InheritedSeed<T> provider throws ArgumentError for a non-null aspect, and a model provider throws for an aspect of the wrong type. Experimental, like the rest of the composition layer.BREAKING CHANGE: debugFillProperties now receives DiagnosticsBuilder instead of List.
Route foundation, tree, and perception diagnostics through a public builder while preserving the version-1 wire contract. Synchronize breaking package versions and workspace dependency constraints, and record the ratified ruling.
BREAKING CHANGE: debugFillProperties now receives DiagnosticsBuilder instead of List.
Refs: genesis-nd7
debugFillProperties now receives a DiagnosticsBuilder — replace properties.add(...) list calls with the builder add(); wire format unchanged.chore(release): genesis foundation-wave — foundation 0.1.2 docs refre…
chore(release): genesis foundation-wave — foundation 0.1.2 docs refre…
genesis_foundation ^0.1.1 below the tree spine and re-export its
dependency-free diagnostics protocol and typed snapshot contract. The
first-class Key types remain owned by genesis_tree.release(tree): 0.1.5 — docs-only, ship the artifact-layer README to p…
release(tree): 0.1.5 — docs-only, ship the artifact-layer README to p…
genesis_tree reconciles desired state into
live identity and stops there — what that identity spawns and owns is the
consumer's, unbundled into four pieces (artifacts / owner / protocol /
affordance scopes), with genesis_typesetting and genesis_perception as
the worked examples. The composition-layer list also catches up to 0.1.4
(MultiChildSeed, the SingleChildSeed/Nest chain).test(tree): extend the A8 throw-after-unmount enumeration to getInher…
test(tree): extend the A8 throw-after-unmount enumeration to getInher…
Add the single-child chain vocabulary. SingleChildStatelessSeed and
SingleChildStatefulSeed (with SingleChildState) are the single-child
analogues of StatelessSeed/StatefulSeed: their build receives the
downstream child to embed (buildWithChild). Nest stacks a list of them
into a vertical spine, each wrapping the next down to one leaf child — the
Nested/MultiProvider shape, generic (no inherited-value semantics baked
in). MultiChildSeed fans out horizontally; Nest composes vertically.
Fully const-constructible: the children are referenced as authored and never
reconstructed — each link's downstream is supplied at the branch layer — so an
unchanged Nest prunes its whole chain on reconcile, while a change to the
leaf or any link propagates through it. EXPERIMENTAL.
Add getInheritedSeedOfExactType<T>() — the dependency-free counterpart of
dependOnInheritedSeedOfExactType<T>(). Same nearest-ancestor lookup, same
value result, but the caller is not registered as a dependent: the
returned value is a snapshot, and a later change to the provided value does
not rebuild the reader. Use it for one-shot reads — grabbing an ambient
service in State.initState, inside an effect, during teardown — and keep
the depend variant wherever the branch must rebuild on change. Available on
Branch, TreeContext, and SproutContext. Breaking for external
TreeContext implementers (a new interface member); handles that wrap
the canonical handle just delegate it.
StatefulBranch now asserts (debug-only) when
dependOnInheritedSeedOfExactType is called during initState or
dispose. In initState the natural cache-the-result pattern goes stale
when the provider changes (initState never re-runs) — read dependency-free
with the new variant, or cache-and-track in didChangeDependencies. In
dispose the branch is unmounting and can never observe a change.
There is deliberately no "get the provider element" lookup (Flutter's
getElementForInheritedWidgetOfExactType): the capability handle never
exposes a Branch.
Breaking: a first-class Key value-type. Seed.key (and Branch.key, TreeContext.key) is now typed Key? instead of Object?. Two concrete kinds ship: Valu
Key value-type. Seed.key (and Branch.key,
TreeContext.key) is now typed Key? instead of Object?. Two concrete
kinds ship: ValueKey<T>(value) (value equality; the type parameter is part
of identity, so ValueKey<int>(1) != ValueKey<num>(1)) and ObjectKey(value)
(identity equality), plus an ergonomic const Key(String) factory that builds
a ValueKey<String>. The typed key gives reconciliation identity intent and
type-safety and a shared identity story for keyed list reconcile.Key is open (abstract, not sealed): domains extend it with their own key
kinds. There is deliberately no GlobalKey — cross-tree lookup is refused
so the tree stays one-way (cross-boundary references pass handles through the
parent) — and no LocalKey layer (vacuous without a global key).key: 'id' with key: ValueKey('id') (or Key('id')),
and seed.key == 'id' comparisons with seed.key == ValueKey('id').MultiChildSeed/MultiChildBranch to the (experimental) composition
layer: a config-declared multi-child container that keyed-reconciles its
List<Seed> children via Branch.updateChildren — the
MultiChildRenderObjectElement analogue, beside the single-child
StatelessSeed/StatefulSeed/Sprout. Matched children (keyed by key,
unkeyed by position) keep their branch identity across rebuilds; new children
mount, removed children unmount, and child order follows children. The
identical-config skip fast path and the duplicate-sibling-key debug guard are
inherited from Branch. Additive; the spine is unchanged.Add a debug assertion that sibling keys are unique within updateChildren (debug-mode only; surfaces duplicate-key reconcile bugs earlier, no release-m
updateChildren
(debug-mode only; surfaces duplicate-key reconcile bugs earlier, no
release-mode behavior change).Docs: package documentation (README, dartdoc) made self-contained for pub.dev.
TreeContext use-after-unmount StateError message (text only; no behavior change).Initial release: the Seed/Branch keyed-reconcile engine — TreeContext (a separate capability handle), TreeOwner, the composition layer (Stateless/Stat
Initial release: the Seed/Branch keyed-reconcile engine — TreeContext (a separate capability handle), TreeOwner, the composition layer (Stateless/Stateful/State, InheritedSeed, Watch, Sprout), and the identical-config skip fast path.
Pre-1.0 and experimental; APIs may change before 1.0.
Your coding agent can read these notes before it upgrades. Set up the MCP server →