fix: address all 9 findings from final calibration code review

- calibration.js: fix baseSignalName('[0]') parity with Go/C++ (>= 0 not > 0)
- calibration.test.js: add assertions for '[0]' edge case in two existing tests
- app.js: remove stale typeof guard around refreshVScaleMenu (always defined)
- app.js: call refreshTrigThresholdField on trig-signal change (both assignment sites)
- index.html: drop maxlength='16' on unit input; normaliseCal is the sole enforcer
- configcheck/main.go: delete dead nextOneOf function (no callers)
- hub_calibration_test.go: delete orphaned waitBroadcast comment (function never existed)
- calibration.go: correct arrayIndexSuffix comment to document known Go/C++ difference
- Docs/StreamHub-API.md: add calibration entry count and unit byte limits to §5 table
- spec: fix configReloaded missing path field, '16 chars'→'16 UTF-8 bytes', StreamString→char[], chain scenario→configcheck program, four→five new frames

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino Ferrari
2026-08-17 07:57:28 +02:00
co-authored by Claude Sonnet 4.6
parent 42f5a726af
commit 1f8592f854
10 changed files with 238 additions and 54 deletions
-34
View File
@@ -150,40 +150,6 @@ func (c *conn) nextSkipping(want string, also []string) (frame, error) {
}
}
// nextOrOptional reads from the background reader, skipping ambient frames,
// and returns (frame, frametype) where frametype is the type of the first
// protocol frame that arrives, regardless of whether it matches want.
// If the optional type arrives instead, that is returned too.
// This is used for the reload sequence where C++ may emit an extra "sources"
// frame after "calibration".
func (c *conn) nextOneOf(want, optional string) (frame, string, error) {
deadline := time.NewTimer(c.timeout)
defer deadline.Stop()
for {
select {
case <-deadline.C:
return frame{}, "", fmt.Errorf("timeout waiting for %q (or %q)", want, optional)
case r, ok := <-c.readCh:
if !ok {
return frame{}, "", fmt.Errorf("reader closed while waiting for %q", want)
}
if r.err != nil {
return frame{}, "", fmt.Errorf("read while waiting for %q: %w", want, r.err)
}
if r.f.Type == want || r.f.Type == optional {
return r.f, r.f.Type, nil
}
// Any other protocol frame is unexpected.
if protocolFrameTypes[r.f.Type] {
return frame{}, "", fmt.Errorf(
"unexpected protocol frame %q while waiting for %q or %q",
r.f.Type, want, optional)
}
fmt.Printf("[skip ambient %q]\n", r.f.Type)
}
}
}
// nextWithin reads from the background reader until a frame with the wanted
// type arrives within d, returning (frame, true) or (frame{}, false). Unlike
// next() it does NOT return an error on timeout, making it suitable for the