fix(k1): gate control dialogue on live state

This commit is contained in:
DCCONSTRUCTIONS
2026-07-18 17:19:21 +03:00
parent a29b38a0d7
commit 36f0c93d2a
14 changed files with 1435 additions and 122 deletions
@@ -0,0 +1,91 @@
# Lab 003 — K1 application-control physical acceptance
- Date: 2026-07-18
- Device scope: one owner-controlled LixelKity K1, firmware `3.0.2`
- Result: **PAUSE — START acknowledgement is not lifecycle acceptance**
This report contains no device identity, application authority, address,
credential, raw MQTT payload or project contents. Private evidence remains in
ignored session storage.
## Safety boundary
The operator was present and confirmed ownership, steady-green standby,
battery/storage, exact direct-LAN target and closed LixelGO. Every request used
QoS 2, retain false, one connection attempt and no automatic retry. The local
point/pose receiver was read-only and independent of the control client.
## Attempt 1
The control client emitted bootstrap ordinals 16. All six QoS2 transactions
completed and five required responses arrived, but the batch-3 response did not
pass exact correlation. The executor stopped before START. K1 remained READY
and steady green; point/pose counts stayed zero.
## Attempt 2
After adding redacted live-response diagnostics, one new explicit permit was
used. All ten pre-START requests and START completed QoS2; all required
responses, including the START response, passed identity/session/action/result
correlation. The eleven publishes completed in approximately `365 ms`.
The device then reported `SCAN_STARTING` for approximately 24 seconds. No point
cloud or pose message arrived. It emitted two identical
`lixel/application/report/system_error` messages with code `0x32040133`, reset
to `OTHER_STATUS` without a project binding and showed a steady-red indicator.
The bounded decoder maps the observed namespace/value as
`0x32040000 + 307 = ALGORITHM_ERROR`. A normal operator power cycle restored
steady green. No guessed STOP or repeated START was sent.
## Canonical-diff finding
Re-audit of two independent owner-operated LixelGO START captures found the
same 14-operation order in both:
1. unbound DeviceInfo;
2. unbound ModelingStatus;
3. unbound GetRtkAdvance;
4. bound time/timezone DeviceConfig;
5. bound DeviceInfo;
6. bound GetRtkAdvance;
7. bound GetNtripProfile;
8. bound GetCloudServerConfig;
9. bound GetRtkAdvance;
10. bound DeviceInfo;
11. bound START;
12. bound ModelingStatus;
13. bound DeviceInfo after initialization;
14. bound ModelingStatus after initialization.
The first retained capture reached START at `+202.423 s`; the faster one at
`+54.130 s`. This is variable operator/UI time, not a fixed scanner timeout.
Both preserved the stage order, sent operation 12 within about one second of
START, sent operations 1314 about 2425 seconds after START and kept the same
control MQTT connection open throughout. Neither capture disconnected or
unsubscribed during initialization.
The same re-audit shows that those wall-clock gaps are not protocol timers.
Requests 16 follow connection, request 7 follows explicit workspace entry,
requests 810 follow opening the project prompt, and START follows the operator's
confirmation. No separate project-name save request exists; the name first
appears in START. In both captures operations 1314 coincide with K1's own
`SCANNING`, bound-project and `init_ready=true` DeviceStatus transition.
Attempt 2 matched the first eleven payload/topic operations but violated the
larger lifecycle: it collapsed the UI stages, omitted operations 1214 and did
not preserve a long-lived control-session owner. The evidence does not prove
which individual deviation caused the device algorithm failure, so none is
treated as the sole cause.
## Code decision
The legacy collapsed `run_bootstrap()` executor now rejects before emission.
The replacement acceptance-only executor uses explicit connection/workspace/
project-prompt checkpoints with no captured-delay replay. It owns operations
114, gates the final refresh on live K1 state, surfaces redacted system errors,
keeps the same socket serviced through explicit STOP and waits for READY plus
operator-confirmed standby. The socket is also serviced between every UI action;
START/STOP permits begin only at their respective confirmations. Standalone
START/STOP are rejected. This remains an
uninstalled synthetic-test-only boundary; no new physical attempt is authorized
by this implementation. Physical double-click remains the canonical fallback.