Lattice: read-only device map + producers + authority-ranked merge & resolve (conformance-pinned)#4147
Draft
mgazza wants to merge 14 commits into
Draft
Lattice: read-only device map + producers + authority-ranked merge & resolve (conformance-pinned)#4147mgazza wants to merge 14 commits into
mgazza wants to merge 14 commits into
Conversation
…resolve) Pure, dependency-free model: Fragment/Node/Sensor/AccessPath, merge_fragments (one node per device by serial, ranked access paths, combined sensors), resolve_sensor (preferred entity), and the device_fragment builder. READ-ONLY by design — control is a separate, deferred model. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
LatticeProjection discovers any component publishing a fragment, merges them into the site map, and resolves a device's sensor to its preferred entity. LatticeComponent (registered, phase 2) rebuilds + logs the merged map when lattice_projection_enable is on; no-op when off (default). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GatewayMQTT.lattice_fragment maps each battery inverter it sees (identity + type) on a local-Modbus access path and references the gateway sensor entities (soc/power/temperature) that already exist. Read-only — no control. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tory) GECloudDirect.lattice_fragment publishes its cloud-reachable devices (topology + soc/power sensor inventory) on a low-preference cloud access path, so a device also seen by the gateway resolves to the gateway entity. Read-only — no control. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
FoxAPI.lattice_fragment publishes its cloud devices (real deviceSN identity + soc/power sensor inventory) on a cloud access path. Read-only — no control. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SolaxAPI.lattice_fragment publishes its cloud plants (topology + soc sensor inventory) on a cloud access path. Read-only — no control. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SolisAPI.lattice_fragment publishes its cloud inverters (topology + soc/power sensor inventory) on a cloud access path. Read-only — no control. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rence
Pure Python port of editor/src/merge-engine.ts: merge(docs) -> {"site", "warnings"}.
Operates on raw dicts (corpus wire shape); independent of existing dataclasses and
does not replace merge_fragments. 16 unit tests cover precedence, tombstones,
bag/wholesale/collection-union overrides, refs, docVersion digest, and errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tionship tombstone Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ases) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…iebreak) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 29, 2026
Add a pure resolve(doc, capability, side, intent, offline, altitude) to lattice.py,
mirroring the lattice-spec reference (editor/src/resolve-engine.ts): read vs control
routing, ranked access-path fallback, aggregate delegation/expansion, ownership,
derived reads, and intent clamping. Returns the observable result dict.
Vendor conformance/resolve/{cases,expected}.json (byte-identical) + a runner that
projects the observable FIELD set and asserts batpred == the reference on all 6 cases.
This makes batpred a provably-identical second-language resolve adopter, alongside the
existing merge corpus.
Reviewed (sonnet) vs the TS line-by-line incl. branches the corpus doesn't cover; folded
in: JS-style number stringification in display labels (integer floats lose the trailing
.0, e.g. cap/2 label), nullish reducer default, and a NaN-intent guard.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Align the merge() site topologyVersion default with the frozen spec and the canonical TS reference (merge-engine.ts) and the gateway merge_eval port. Only reached when an input doc omits topologyVersion (the corpus always sets it, so all conformance cases are unaffected) — this keeps the Python and C++ merge ports consistent on that fallback branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mirror lattice-spec merge fix (PR #28): a tombstone is a barrier — when a node is re-added above a removal, only contributors ranked strictly above the highest tombstone participate in _merge_node, so sub-barrier (lower-authority) discovery data is not resurrected. Re-vendor the 14-case conformance/merge corpus (adds the 'tombstone-barrier' golden) which verifies it. 13->14 corpus cases pass; all lattice tests green (32). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Single consolidated draft for the Lattice work (supersedes the stacked drafts #4081 / #4082 / #4084 — closing those in favour of this one).
All read-only and flag-gated (
lattice_projection_enable, default off) — no control, no behavioural change when disabled.What's here
apps/predbat/lattice.py) — pure model +merge_fragments(union device map) +resolve_sensor. No PredBat/HA deps; unit-tested standalone.device_fragment.lattice_projection.py+lattice_component.py) — merges producer fragments into one site device map; flag-gated component + enable switch.merge) — a pure mirror of the lattice-spec TypeScript reference (editor/src/merge-engine.ts): identity-keyed, authority/recency precedence, per-field/bag/wholesale/collection-union override, removal tombstones, synthetic provenance.conformance/merge/corpus (apps/predbat/tests/lattice_merge_corpus/) + runner pinsmergeto the identical 13-case golden the lattice-spec TS reference passes. This makes batpred the first provably-identical second-language implementation of the merge contract.Tests
apps/predbat/test_lattice.py+test_lattice_merge.py(18) +test_lattice_merge_corpus.py(13 subtests) — all green; pre-commit (interrogate/black/ruff/cspell) passing.Spec & guide:
Predictive-Cloud-Ltd/lattice-spec(schema,conformance/,IMPLEMENTING.md).Draft — read-slice + merge layer; control is a separate, deferred model.
Update: resolve corpus adopted
Adds a pure
resolve(doc, capability, side, intent, offline, altitude)tolattice.py, mirroring the lattice-spec reference (editor/src/resolve-engine.ts): read vs control routing, ranked access-path fallback, aggregate delegation/expansion, ownership, derived reads, and intent clamping. Vendorsconformance/resolve/{cases,expected}.json(byte-identical) with a runner that asserts batpred == the reference on all 6 cases — making batpred a provably-identical second-language adopter of both merge and resolve.