Skip to content

Commit 448b546

Browse files
committed
Add lazy validation completeness for section and hot-water group parameters
1 parent 33de21f commit 448b546

6 files changed

Lines changed: 290 additions & 0 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
schema: spec-driven
3+
created: 2026-07-16
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
## Context
2+
3+
`SectionValidator` lazily validates device parameter support before a section or
4+
hot-water group is read. It currently stores completion as a section-wide set in
5+
`APIValidator` and a group-wide set in `SectionValidator`. An `include` request
6+
validates only a subset but records that coarse completion state, so a later
7+
request for different names or all names can skip validation.
8+
9+
The resulting configuration has not established whether every requested
10+
parameter is supported. For normal sections, an unvalidated parameter can remain
11+
in the configuration and later produce a strict response-mapping failure. For
12+
hot water, the cache contains only the first subset and later reads silently use
13+
that incomplete cache.
14+
15+
## Goals / Non-Goals
16+
17+
**Goals:**
18+
19+
- Record lazy-validation coverage by parameter ID for sections and hot-water
20+
groups.
21+
- Revalidate only the parameter IDs required by a later request when they have
22+
not already been covered.
23+
- Retain the existing public method signatures, include-filter validation, and
24+
per-section/group locking model.
25+
- Add regression tests for sequential filtered and unfiltered access.
26+
27+
**Non-Goals:**
28+
29+
- Change the public `include` API or make it accept parameter IDs.
30+
- Alter device-response parsing, model serialization, or unsupported-parameter
31+
rules.
32+
- Retry or cache failed validation requests.
33+
34+
## Decisions
35+
36+
### Track covered parameter IDs per validation owner
37+
38+
`APIValidator` will maintain a mapping from section name to the set of parameter
39+
IDs whose support was checked. `SectionValidator` will maintain the equivalent
40+
mapping for hot-water group names. Completion for a request is determined by
41+
whether its requested IDs are a subset of that owner’s covered IDs.
42+
43+
Parameter IDs are chosen over parameter names because they are the identifiers
44+
sent to BSB-LAN and remain unambiguous if a configuration ever aliases a name.
45+
When a response establishes an ID is unsupported, it is removed from the active
46+
configuration/cache but remains covered, preventing needless repeated probes.
47+
48+
Alternative considered: avoid persisting any completion after an `include`
49+
request. This avoids the defect but discards useful knowledge and repeatedly
50+
validates already checked parameters. Parameter-level coverage keeps lazy
51+
loading efficient while remaining correct.
52+
53+
### Derive requested IDs before the one-time gate
54+
55+
Each ensure method will first resolve the configured IDs for its section or
56+
group, applying `include` when present. Its lock’s fast and post-lock checks will
57+
compare that specific requested-ID set to coverage rather than use a coarse
58+
section/group marker. A full request resolves all currently configured IDs and
59+
therefore completes only after each is covered.
60+
61+
An include filter that matches no IDs will not add coverage or mark a group or
62+
section complete. Existing downstream include validation remains responsible for
63+
returning the appropriate invalid-include error.
64+
65+
Alternative considered: retain a boolean for full validation plus a separate
66+
partial set. This duplicates state and makes configuration changes harder to
67+
reason about; one coverage mapping expresses both cases.
68+
69+
### Preserve locks and recheck coverage after waiting
70+
71+
The existing per-section and per-group locks remain in place. The completion
72+
predicate will calculate coverage for the current requested IDs both before and
73+
after lock acquisition. Concurrent calls requesting different subsets therefore
74+
serialize safely, and the second call still validates its uncovered IDs.
75+
76+
## Risks / Trade-offs
77+
78+
- [Configuration mutation during validation] → Derive the requested IDs from
79+
the current configuration at each completion check; removed unsupported IDs
80+
no longer need validation.
81+
- [Stale internal tests inspect completion sets] → Update tests to assert
82+
parameter coverage and externally observable request/cache behavior instead
83+
of obsolete whole-group completion.
84+
- [Additional first-read requests] → A later request for previously unrequested
85+
parameters necessarily makes one validation request; already covered IDs are
86+
not re-requested.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
## Why
2+
3+
Lazy validation currently records a section or hot-water group as fully
4+
validated after a request filtered with `include`. This can leave unsupported
5+
parameters in a section or leave the hot-water cache incomplete, causing later
6+
unfiltered reads to skip necessary validation and return incomplete data or fail
7+
while mapping a device response.
8+
9+
## What Changes
10+
11+
- Track validation coverage at the parameter level for sections and hot-water
12+
groups instead of treating any successful filtered request as complete.
13+
- Ensure a later request validates parameter names that an earlier `include`
14+
request did not cover.
15+
- Keep validation completion correct when an include filter has no matching
16+
parameters.
17+
- Add focused regression coverage for filtered-then-unfiltered and
18+
differently-filtered reads.
19+
20+
## Capabilities
21+
22+
### New Capabilities
23+
24+
- `lazy-validation-completeness`: Lazy section and hot-water validation covers
25+
every parameter required by each request before that request uses the cached
26+
configuration.
27+
28+
### Modified Capabilities
29+
30+
- None.
31+
32+
## Impact
33+
34+
- Affected code: `src/bsblan/_validation.py`, `src/bsblan/utility.py`, and the
35+
lazy section and hot-water read paths that use their validation state.
36+
- Affected tests: validation, include-filter, and hot-water regression tests.
37+
- Public API: no signature changes; `include` calls may perform an additional
38+
validation request when they need parameters not checked by a prior call.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
## ADDED Requirements
2+
3+
### Requirement: Section validation covers every requested parameter
4+
5+
Before a lazy section read uses its configured parameters, the client SHALL
6+
validate support for every parameter ID required by that read. A prior validation
7+
of a different included subset SHALL NOT make unvalidated parameter IDs appear
8+
validated. The client SHALL not repeat validation for IDs already covered unless
9+
validation state is explicitly reset.
10+
11+
#### Scenario: Filtered section read followed by unfiltered read
12+
13+
- **WHEN** a section is first read with `include` selecting one parameter and a
14+
later read requests the complete section
15+
- **THEN** the later read validates every configured parameter ID not checked by
16+
the first read before fetching the complete section
17+
18+
#### Scenario: Differently filtered section read
19+
20+
- **WHEN** a section is read with one included parameter and later read with a
21+
different included parameter
22+
- **THEN** the second read validates the newly requested parameter ID
23+
- **AND** it does not revalidate the parameter ID already covered by the first
24+
read
25+
26+
#### Scenario: Unsupported parameter discovered by a later read
27+
28+
- **WHEN** a later section read validates a previously uncovered parameter ID
29+
that the device does not support
30+
- **THEN** the client removes that parameter from the active configuration
31+
- **AND** subsequent reads do not request that unsupported parameter
32+
33+
### Requirement: Hot-water group validation covers every requested parameter
34+
35+
Before a hot-water group read uses its cached parameters, the client SHALL
36+
validate and cache every parameter ID required by that read. A prior validation
37+
of an included subset SHALL NOT make the group complete for other parameter IDs.
38+
39+
#### Scenario: Filtered hot-water read followed by complete group read
40+
41+
- **WHEN** a hot-water group is first read with `include` selecting a subset and
42+
later read without `include`
43+
- **THEN** the later read validates and caches every remaining supported
44+
parameter ID in that group before it fetches group data
45+
46+
#### Scenario: Differently filtered hot-water read
47+
48+
- **WHEN** a hot-water group is read with one included parameter and later read
49+
with a different included parameter
50+
- **THEN** the second read validates and caches the newly requested parameter ID
51+
- **AND** it does not revalidate the parameter ID already covered by the first
52+
read
53+
54+
### Requirement: Empty include results do not complete validation
55+
56+
When an include filter selects no parameter IDs in a section or hot-water group,
57+
the client SHALL NOT record that owner as complete or add parameter coverage.
58+
59+
#### Scenario: Later valid read after no-match include
60+
61+
- **WHEN** an include filter matches no parameters and a later request selects
62+
one or more valid parameters from the same section or hot-water group
63+
- **THEN** the later request validates its selected parameter IDs normally
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
## 1. Parameter-Level Validation Coverage
2+
3+
- [x] 1.1 Replace coarse section completion tracking in `APIValidator` with
4+
per-section parameter-ID coverage, including reset behavior.
5+
- [x] 1.2 Update lazy section validation to derive the current requested IDs,
6+
gate on their coverage, and retain unsupported-ID removal behavior.
7+
- [x] 1.3 Replace coarse hot-water group completion tracking with per-group
8+
parameter-ID coverage and keep the cache synchronized with validated IDs.
9+
- [x] 1.4 Ensure empty include-filter results add no coverage and do not mark a
10+
section or hot-water group complete.
11+
12+
## 2. Regression Coverage
13+
14+
- [x] 2.1 Add section tests for filtered-then-unfiltered and
15+
differently-filtered reads, asserting uncovered IDs are validated once.
16+
- [x] 2.2 Add a section test showing a later-discovered unsupported ID is
17+
removed before the complete read is mapped.
18+
- [x] 2.3 Update hot-water include tests to assert a partial request does not
19+
complete the group, then add filtered-then-unfiltered and
20+
differently-filtered regression cases.
21+
- [x] 2.4 Update the empty include-filter test to assert no completion state is
22+
recorded and a later valid request performs validation.
23+
- [x] 2.5 Retain or extend locking coverage to prove sequentially serialized
24+
requests recheck their own parameter coverage.
25+
26+
## 3. Validation
27+
28+
- [x] 3.1 Run focused validation and include-filter tests with `--no-cov`.
29+
- [x] 3.2 Run `uv run prek run --all-files` and resolve all reported failures.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# lazy-validation-completeness
2+
3+
## Purpose
4+
5+
Lazy section and hot-water validation must record the parameter IDs it has
6+
actually checked so filtered reads cannot suppress validation required by later
7+
requests.
8+
9+
## Requirements
10+
11+
### Requirement: Section validation covers every requested parameter
12+
13+
Before a lazy section read uses its configured parameters, the client SHALL
14+
validate support for every parameter ID required by that read. A prior validation
15+
of a different included subset SHALL NOT make unvalidated parameter IDs appear
16+
validated. The client SHALL not repeat validation for IDs already covered unless
17+
validation state is explicitly reset.
18+
19+
#### Scenario: Filtered section read followed by unfiltered read
20+
21+
- **WHEN** a section is first read with `include` selecting one parameter and a
22+
later read requests the complete section
23+
- **THEN** the later read validates every configured parameter ID not checked by
24+
the first read before fetching the complete section
25+
26+
#### Scenario: Differently filtered section read
27+
28+
- **WHEN** a section is read with one included parameter and later read with a
29+
different included parameter
30+
- **THEN** the second read validates the newly requested parameter ID
31+
- **AND** it does not revalidate the parameter ID already covered by the first
32+
read
33+
34+
#### Scenario: Unsupported parameter discovered by a later read
35+
36+
- **WHEN** a later section read validates a previously uncovered parameter ID
37+
that the device does not support
38+
- **THEN** the client removes that parameter from the active configuration
39+
- **AND** subsequent reads do not request that unsupported parameter
40+
41+
### Requirement: Hot-water group validation covers every requested parameter
42+
43+
Before a hot-water group read uses its cached parameters, the client SHALL
44+
validate and cache every parameter ID required by that read. A prior validation
45+
of an included subset SHALL NOT make the group complete for other parameter IDs.
46+
47+
#### Scenario: Filtered hot-water read followed by complete group read
48+
49+
- **WHEN** a hot-water group is first read with `include` selecting a subset and
50+
later read without `include`
51+
- **THEN** the later read validates and caches every remaining supported
52+
parameter ID in that group before it fetches group data
53+
54+
#### Scenario: Differently filtered hot-water read
55+
56+
- **WHEN** a hot-water group is read with one included parameter and later read
57+
with a different included parameter
58+
- **THEN** the second read validates and caches the newly requested parameter ID
59+
- **AND** it does not revalidate the parameter ID already covered by the first
60+
read
61+
62+
### Requirement: Empty include results do not complete validation
63+
64+
When an include filter selects no parameter IDs in a section or hot-water group,
65+
the client SHALL NOT record that owner as complete or add parameter coverage.
66+
67+
#### Scenario: Later valid read after no-match include
68+
69+
- **WHEN** an include filter matches no parameters and a later request selects
70+
one or more valid parameters from the same section or hot-water group
71+
- **THEN** the later request validates its selected parameter IDs normally

0 commit comments

Comments
 (0)