Skip to content

release: 0.22.0 (root capabilities, extend, idempotent materialization) - #71

Merged
dcj merged 1 commit into
mainfrom
release/0.22.0
Aug 21, 2026
Merged

release: 0.22.0 (root capabilities, extend, idempotent materialization)#71
dcj merged 1 commit into
mainfrom
release/0.22.0

Conversation

@dcj

@dcj dcj commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Bumps __version__ to 0.22.0, promotes [Unreleased] to [0.22.0], adds the tag link. No code changes.

Issue Change
#64 node_id callable, so one device can carry two instances of a capability
#65 DeviceTreeBuilder contract: model ownership, and the limit of add()'s ordering
#66 Data loss in 0.21.0's headline feature. The builder replaced properties in a model it does not own, discarding live values, callbacks and entity_setters. A producer that wired inbound control lost the actuator while $description kept advertising settable: true.
#67 A child could silently shadow an ancestor's or a sibling's id, putting two devices on the same topics. Plus add_root_capabilities(), the feature it was filed for.
#68 extend(), so an existing device can grow a capability. The previous workaround dropped properties from $description while leaving their retained topics on the broker.

Minor rather than patch: three new public methods. #66 is the reason not to sit on it, since 0.21.0 is live with that data loss.

Worth reading in the diff

Materialization is now idempotent at three levels: the node, the property, and the state transition itself. That last one is the substantive change. An empty state_transition() still emits init then ready, and that edge forces every controller on the bus to resync, so a re-declaration that changes nothing must not cost one. Found by a test asserting extend() publishes nothing on a re-declare, which got two publishes: the content was already idempotent, the state flap was not.

Verification

  • 680 tests pass (600 at 0.20.1, 653 at 0.21.0)
  • ruff check / ruff format --check clean; markdownlint clean
  • python -m build produces both artifacts; wheel METADATA reads Version: 0.22.0
  • Version agrees across ebus_sdk.__version__, pyproject.toml's dynamic attr, and the setup.py regex shim

🤖 Generated with Claude Code

Bumps __version__ to 0.22.0 (single source of truth), promotes Unreleased
to [0.22.0], and adds the tag link definition.

  #64  node_id callable, so one device can carry two instances of a
       capability
  #65  DeviceTreeBuilder contract: model ownership, and the limit of
       add()'s ordering
  #66  the builder replaced properties in a model it does not own,
       discarding live values, callbacks and entity_setters. A producer
       that wired inbound control lost the actuator while $description
       kept advertising settable: true. Data loss in 0.21.0's headline
       feature.
  #67  a child could silently shadow an ancestor's id, or a sibling's,
       putting two devices on the same topics. Plus the feature it was
       filed for: add_root_capabilities(), so a root can carry its own
       capabilities rather than only parenting children.
  #68  extend(), so a device that already exists can grow a capability.
       The previous workaround dropped properties from $description while
       leaving their retained topics on the broker.

Minor rather than patch: three new public methods. #66's fix is the
reason not to sit on it, since 0.21.0 is live with that data loss.

Materialization is now idempotent at three levels (node, property, and
the state transition itself), which is what makes a re-fired incremental
lifecycle a genuine no-op. The third matters most: an empty
state_transition still emits init -> ready, and that edge forces every
controller on the bus to resync.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dcj
dcj merged commit 4bb4577 into main Aug 21, 2026
5 checks passed
@dcj
dcj deleted the release/0.22.0 branch August 21, 2026 01:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant