Skip to content

schema-1 1.1.1: a priority with no $settable is locked, not open - #170

Merged
cayossarian merged 5 commits into
mainfrom
fix/never-backup-is-the-absence-of-settable
Aug 27, 2026
Merged

schema-1 1.1.1: a priority with no $settable is locked, not open#170
cayossarian merged 5 commits into
mainfrom
fix/never-backup-is-the-absence-of-settable

Conversation

@cayossarian

@cayossarian cayossarian commented Aug 27, 2026

Copy link
Copy Markdown
Member

SpanCircuitSnapshot.is_never_backup and the priority write target read a declared load-shed/priority that carries no $settable as locked, where they read it as settable before. Homie 5 defaults the attribute to false; the reference publisher SDK emits settable only when true (never false); production captures publish it explicitly on every unlocked property and omit it on locked ones; the migration guide maps never-backup to $settable = !never-backup. The relay already read absence this way — the two now share one reader, description.declared_settable.

The sweep behind it: adoption and extension decided settability with bool(definition.get("settable", False)), so a text "false" (or "1", "yes") authorised a write; they use the same reader now. when_unannotated is gone. The SchemaAdapter.set_circuit_priority_target docstring in core stated the old rule and is corrected on this branch; core is not bumped — the text rides with the next core release.

Release: span-panel-api-schema-1 1.1.1 only. Floor on core unchanged (>=3.1.0,<4.0).

mypy --strict clean (41 files); ruff clean; 1161 passed, 13 skipped.

Homie 5 defaults the attribute to false and the eBus SDK's description
builder emits it only when a property is settable, so a conforming
publisher describes a never-backup circuit by omitting `$settable` on
`load-shed/priority` rather than by publishing `false`. Both mutations
fail against the current permissive default, which reads silence as
permission and offers a priority control on exactly the circuits
commissioned not to accept one.

Two premise tests come with them, because both mutations edit an
attribute the producer publishes: every circuit in the capture announces
`settable: true` explicitly, so the permissive default was never the
thing protecting this fixture, and a capture that stopped announcing it
would make the mutations indistinguishable from the shipped state.
`priority_is_settable` read a declared `load-shed/priority` carrying no
`$settable` as settable, so a circuit commissioned never-backup reported
`is_never_backup=False` and the adapter resolved a write topic for a
priority the panel refuses. Homie 5 defaults the attribute to false and
a conforming publisher emits it only where a write is accepted, so
omission is how a lock is announced -- the same reading the relay
already used, and the one the migration guide's `$settable =
!never-backup` mapping implies.

The justification for the permissive default was firmware that publishes
no attribute at all; the vendored capture announces `settable: true`
explicitly on every circuit's priority, so no producer here relied on
it.

With both callers answering absence the same way, `when_unannotated` is
a knob nothing turns and goes. The rule it encoded moves to
`description.declared_settable`, which is now the only reader of
`$settable`: `charge_limit` was asking the same question with a second
copy of the answer, and its stricter string handling -- only `"true"`
authorises -- is the one kept, since a value that is neither the boolean
nor that word has not said what it means.
…ises a write

The sweep behind the priority fix. Adoption and extension answered the
same question with a second expression -- `bool(definition.get(
"settable", False))` -- which agrees on the default and disagrees on
text: Homie attributes travel as strings, and `bool("false")` is True,
so the declaration that most explicitly refuses a write was minting a
set topic for an uncurated device. Both now read
`description.declared_settable`.

`SchemaAdapter.set_circuit_priority_target` documented the rule the
adapter no longer follows, telling every implementer that an absent
`$settable` on a declared `load-shed/priority` means settable. It says
what the attribute's absence actually announces.

The flat adapter needs nothing: it reads `never-backup` as a published
value, not as mutability, and never consults `$settable`.
Only the adapter changed, so only the adapter is released -- RELEASE.md's
rule, and the one the root changelog entry would have had to contradict
in its own first sentence to justify a core bump for a docstring.

`SchemaAdapter.set_circuit_priority_target`'s corrected docstring stays
on the branch and rides out with the next release that has a reason of
its own; a wrong sentence in the shipped 3.1.1 wheel is worth one
release cycle of patience, not a release cycle of its own.

Neither floor moves. The adapter asks nothing new of the bootstrap and
the bootstrap's extras ask nothing new of the adapter, so every pairing
that resolved before still resolves.
Both modules had grown the same assertion over the same capture -- every
circuit declares `load-shed/priority` with `settable: true` -- written
twice because each was justifying its own mutation. One of them can go,
and it is the snapshot module's: the mutations that most need the
premise are the adapter's, and a premise asserted beside the thing it is
the premise of is the one that gets read when it fails.

The survivor takes over the deleted test's two jobs. It carries the
non-vacuity guard, now `len(circuits) == 5` in the spelling the relay
invariant beside it already uses, so a capture whose circuits stopped
matching the type suffix fails here instead of passing an empty loop.
And it says what the deleted docstring said: this is the standing answer
to the argument the permissive default rested on, firmware that
publishes no attribute at all.
@cayossarian
cayossarian merged commit a9f2d91 into main Aug 27, 2026
6 checks passed
@cayossarian
cayossarian deleted the fix/never-backup-is-the-absence-of-settable branch August 27, 2026 06:12
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