fix(k1): gate control dialogue on live state
This commit is contained in:
@@ -21,7 +21,7 @@ Each gate produces evidence and an explicit GO, PAUSE or BLOCKED result.
|
||||
| Stage 7 observation archive | GO (point/pose/telemetry contract) — durable catalog, recovery, capture-clock-bounded RRD preparation, archived metric time series, saved-session timeline and atomic playback are implemented |
|
||||
| Stage 7 recorded cameras | GO (contract), acceptance pending — acquisition-owned fMP4 archive and player are implemented/tested; one real archived K1 camera plus point-cloud session has not passed playback yet |
|
||||
| Plugin isolation | GO (laboratory control plane) — vendor backend/frontend and optional scene controls are plugin-owned; manifest/runtime descriptor parity, versioned handshake, lifecycle health and transport correlation fail closed while execution remains in-process |
|
||||
| K1 application control | PAUSE (first physical bootstrap failed closed before START) — plugin v0.4.0 runtime remains dormant/write-disabled; the uninstalled acceptance transport completed one connection, six QoS2 bootstrap publishes and five correlated responses, then rejected one live batch-3 response; K1 remained READY, START was not emitted, retry is forbidden and the temporary Keychain item was deleted |
|
||||
| K1 application control | PAUSE (accepted START followed by `ALGORITHM_ERROR`) — first live attempt stopped before START on a batch-3 correlation failure; a second attempt correlated all 10 pre-START requests plus START but collapsed UI stages into 365 ms and omitted the retained post-START/control-session lifecycle. The collapsed path and standalone START/STOP are disabled. An uninstalled offline executor now uses explicit UI checkpoints plus live DeviceStatus gates; no further physical write is authorized yet |
|
||||
| Stage 8 product storage | PAUSE — retention, replication, encryption, capacity monitoring and long-run browser/WASM stress remain deployment gates |
|
||||
|
||||
USB project copying remains optional ground truth rather than a blocker for the
|
||||
@@ -61,7 +61,26 @@ required responses through batch 3, but the orchestrator raised
|
||||
`ApplicationBootstrapError` while correlating that batch. No START was emitted;
|
||||
live DeviceStatus stayed READY and the local point/pose counts remained zero.
|
||||
The local capture was sealed and the temporary Keychain item was deleted.
|
||||
Physical START/STOP therefore remain untested; the button is the safe fallback.
|
||||
The second physical attempt then correlated all ten bootstrap requests and one
|
||||
START success response. It nevertheless did not reproduce the full LixelGO
|
||||
lifecycle: all eleven publishes completed in 365 ms, the process did not retain
|
||||
the control session through initialization, and it omitted the immediate and
|
||||
post-initialization status reads present in both retained LixelGO START captures.
|
||||
K1 reported `SCAN_STARTING` for about 24 seconds, emitted system error
|
||||
`0x32040133` twice (the recovered `ALGORITHM_ERROR` namespace/value), returned
|
||||
to `OTHER_STATUS`, produced zero point/pose frames and showed steady red. The
|
||||
operator restored steady green through a normal power cycle. The legacy
|
||||
`run_bootstrap()` path now rejects before emission. The offline acceptance path
|
||||
maps requests 1–6 to connection, request 7 to explicit scan-workspace entry,
|
||||
requests 8–10 to explicit project-prompt opening and request 11 to the operator's
|
||||
START confirmation. Captured human delays are not replayed or treated as minimum
|
||||
timeouts. After the immediate operation-12 read, operations 13–14 wait for the
|
||||
same bound K1 to report `SCANNING`, a bound project and `init_ready=true`.
|
||||
The same transport is then serviced until an explicit STOP request; post-STOP
|
||||
ownership waits for live `READY` plus physical standby confirmation. System-error
|
||||
and status reports are decoded into redacted safety state. This path is not
|
||||
wired into the plugin runtime/UI and has only synthetic regression coverage;
|
||||
physical STOP/save remains untested and the button is the safe fallback.
|
||||
|
||||
The Stage 6 live path uses a bounded raw-first bridge: loss in the visualization
|
||||
queue cannot discard MQTT evidence. The queue holds four preview messages;
|
||||
@@ -280,8 +299,9 @@ useful stream is decoded or structurally identified.
|
||||
- firmware or internal-Linux analysis;
|
||||
- physical end-to-end shared-timeline playback for a newly archived session
|
||||
containing point cloud plus one selected K1 camera;
|
||||
- OS-independent plugin/edge authority provider, redacted live-response
|
||||
diagnostics for bootstrap batch 3, a newly permitted operator-present full
|
||||
START/STOP attempt and stable-artifact proof after STOP;
|
||||
- OS-independent plugin/edge authority provider, PCAP-to-executor transcript
|
||||
regression, runtime ownership integration, a separately reviewed and newly
|
||||
permitted operator-present START/STOP attempt, and stable-artifact proof after
|
||||
STOP;
|
||||
- long-running large-session WebViewer/WASM memory telemetry;
|
||||
- production retention, replication, encryption and cross-platform packaging.
|
||||
|
||||
@@ -188,14 +188,31 @@ repository shadow bootstrap reproduces all ten retained payloads and their
|
||||
topic order byte-for-byte. Time sync is the only mutation before START; the
|
||||
other nine requests are reads.
|
||||
|
||||
The retained request/response timing further divides the dialogue into five
|
||||
bounded batches. DeviceInfo response establishes identity before later bound
|
||||
requests. Required response barriers are correlated by topic, exact session,
|
||||
vendor identity, application authority and numeric success. The initial
|
||||
ModelingStatus request is intentionally not treated as a required synchronous
|
||||
response: the clean cycle continued without one, and readiness belongs to the
|
||||
live DeviceStatus gate. The offline orchestrator completes over the retained
|
||||
payloads without substitution or skipped requests.
|
||||
The first ten requests use five response-barrier batches, but those barriers are
|
||||
not the whole application lifecycle. Two independent owner-operated START
|
||||
captures contain the same 14-operation order: the ten requests above, START,
|
||||
one bound `ModelingStatus` read, then a bound `DeviceInfo` plus
|
||||
`ModelingStatus` refresh about 24–25 seconds after START. The first capture
|
||||
reached START 202.423 seconds after its initial DeviceInfo; the faster capture
|
||||
reached it after 54.130 seconds. This variation is operator/UI time, while the
|
||||
stage order is invariant. In both captures the original control MQTT connection
|
||||
remained open throughout initialization and the later refresh; no DISCONNECT or
|
||||
UNSUBSCRIBE occurred. DeviceInfo response establishes identity before later
|
||||
bound requests. Required response barriers are correlated by topic, exact
|
||||
session, vendor identity, application authority and numeric success. The
|
||||
initial and immediate post-START ModelingStatus reads are intentionally not
|
||||
treated as mandatory synchronous responses. Readiness belongs to live
|
||||
DeviceStatus plus point/pose observation.
|
||||
|
||||
The UI/event correlation is also fixed by the retained capture. Requests 1–6
|
||||
follow successful data connection. Entering the scan workspace causes request
|
||||
7. Opening the record/project-name prompt causes reads 8–10. The project name is
|
||||
not sent by a separate save mutation: it first appears in the START payload when
|
||||
the operator confirms the prompt. K1 then reports `SCAN_STARTING`; completion is
|
||||
the live transition to `SCANNING` with a bound project and `init_ready=true`.
|
||||
Operations 13–14 coincide with that state in both captures. The observed
|
||||
24–25-second initialization duration is therefore evidence/telemetry, not a
|
||||
hard-coded transition delay.
|
||||
|
||||
The repository now contains an inert bounded encoder/response parser and a
|
||||
fail-closed device-status state machine for this exact profile. A live-only
|
||||
@@ -230,7 +247,32 @@ connection and emitted bootstrap ordinals 1–6. All six QoS 2 publishes complet
|
||||
and five required responses were collected, but exact correlation rejected one
|
||||
response in batch 3. The executor stopped before building or publishing START;
|
||||
K1 remained `READY`, project binding stayed absent and point/pose remained zero.
|
||||
No automatic retry was attempted.
|
||||
No automatic retry was attempted. A second explicitly permitted attempt then
|
||||
correlated all ten bootstrap responses and one START success response, with 11
|
||||
QoS2 completions, but it compressed the exchange into 365 ms and ended without
|
||||
the retained post-START reads or durable control-session ownership. K1 remained
|
||||
in `SCAN_STARTING` for about 24 seconds, emitted two identical
|
||||
`report/system_error` values `0x32040133`, returned to `OTHER_STATUS`, produced
|
||||
no point/pose frames and showed steady red. The bounded system-error decoder maps
|
||||
the `0x32040000 + 307` value to the recovered `ALGORITHM_ERROR` state. A normal
|
||||
operator power cycle restored steady green.
|
||||
|
||||
This disproves the earlier assumption that byte-matched pre-START payloads plus
|
||||
a correlated START acknowledgement are sufficient acceptance. The legacy
|
||||
collapsed `run_bootstrap()` executor now rejects before emission. Its
|
||||
replacement is an uninstalled acceptance-only session owner. It requires the
|
||||
observed connection, workspace-entry and project-prompt checkpoints instead of
|
||||
wall-clock floors, sends the immediate post-START ModelingStatus read, services
|
||||
the same MQTT socket until live `SCANNING + project + init_ready`, then emits the
|
||||
DeviceInfo/ModelingStatus refresh. It continues servicing that socket until an
|
||||
explicit STOP request and afterwards until live `READY` plus operator-confirmed
|
||||
standby. System-error and DeviceStatus reports are decoded into redacted safety
|
||||
state; a fault forbids further automatic action. Standalone START/STOP are
|
||||
disabled. MQTT keepalive/report processing also continues while the operator is
|
||||
between UI actions; the 15–120-second command permit is created at the actual
|
||||
START or STOP confirmation, not at connection time. This path is
|
||||
synthetic-test-only and remains outside facade/UI, so it
|
||||
does not authorize a new physical attempt.
|
||||
|
||||
The one-time Keychain administration command uses `security -w` as the final
|
||||
argument so Apple's own TTY prompt receives the authority. Mission Core never
|
||||
|
||||
@@ -37,10 +37,14 @@ K1 application control is exact-profile, live-bound and fail-closed.
|
||||
3. The BLE-selected transport is followed by an unbound DeviceInfo exchange.
|
||||
Its live vendor ID, serial, activation and FW 3.0.2 facts form the transient
|
||||
device binding; a saved profile is optional metadata, not protocol authority.
|
||||
4. The ten retained pre-START requests keep their exact order and response
|
||||
boundaries. The only mutation is the observed time/timezone sync; the other
|
||||
nine requests are reads. No request is batched, skipped or automatically
|
||||
retried.
|
||||
4. The complete retained START lifecycle keeps its 14-operation order, stage
|
||||
boundaries and one continuous control MQTT session. The first ten operations
|
||||
are pre-START; operation 11 is START; operation 12 is a bound ModelingStatus
|
||||
read; operations 13–14 are the post-initialization DeviceInfo/ModelingStatus
|
||||
refresh. The only preparatory mutation is time/timezone sync. No stage is
|
||||
collapsed, skipped or automatically retried. Captured wall-clock gaps are
|
||||
operator/UI timing, not protocol delays. Stage progression uses explicit UI
|
||||
actions and live K1 state reports.
|
||||
5. Live DeviceInfo binding must agree with the live DeviceStatus stream before
|
||||
START/STOP planning. Identity drift, malformed data, inactive equipment,
|
||||
profile mismatch or an unexpected lifecycle state fails closed.
|
||||
@@ -55,7 +59,7 @@ K1 application control is exact-profile, live-bound and fail-closed.
|
||||
quiescence/evidence sealing, READY plus steady green, then independent native
|
||||
project verification.
|
||||
|
||||
## Recovered pre-START sequence
|
||||
## Recovered START sequence
|
||||
|
||||
The clean cycle contains:
|
||||
|
||||
@@ -70,6 +74,9 @@ The clean cycle contains:
|
||||
9. bound `GetRtkAdvanceRequest`;
|
||||
10. bound `DeviceInfoRequest`;
|
||||
11. bound `ModelingRequest` START.
|
||||
12. bound `ModelingStatusRequest`;
|
||||
13. bound `DeviceInfoRequest` after static initialization;
|
||||
14. bound `ModelingStatusRequest` after static initialization.
|
||||
|
||||
Normal sessions are `${device_id_or_empty}:${MessageType}`. Time sync uses the
|
||||
captured special relation
|
||||
@@ -115,9 +122,20 @@ An unknown post-publish outcome can only be reconciled physically/status-wise;
|
||||
the same operation key can never be attempted again by that transport.
|
||||
|
||||
The acceptance executor requires a 15–120 second single-action permit backed by
|
||||
five explicit operator confirmations. START cannot skip the five recovered
|
||||
bootstrap batches; STOP uses a separate permit. These types are not imported by
|
||||
the facade, declared as plugin actions or represented by UI controls.
|
||||
five explicit operator confirmations. After the failed 2026-07-18 physical
|
||||
attempt proved that five response batches alone are insufficient, the collapsed
|
||||
bootstrap entry point and standalone START/STOP were disabled. The uninstalled
|
||||
replacement binds requests 1–6 to connection, request 7 to scan-workspace entry,
|
||||
requests 8–10 to project-prompt entry and START to a separate operator permit.
|
||||
There is no separate project-name mutation; the validated name is carried by
|
||||
START. Operations 13–14 are gated by bound `SCANNING`, project presence and
|
||||
`init_ready`, not by the observed 24–25-second duration. The same owner services
|
||||
MQTT through explicit STOP and waits for live READY plus operator-confirmed
|
||||
standby. Fault/status observations are redacted and any fault forbids automatic
|
||||
continuation. The socket remains serviced during operator/UI waits, and each
|
||||
short action permit is created at its button confirmation rather than at
|
||||
connection time. These types are synthetic-test-only, not imported by the facade,
|
||||
declared as plugin actions or represented by UI controls.
|
||||
|
||||
`MacOSKeychainApplicationAuthorityProvisioner` invokes Apple's interactive
|
||||
`security add-generic-password ... -w` prompt with `-w` last. The private value
|
||||
@@ -133,10 +151,11 @@ transport:
|
||||
|
||||
1. provision the reviewed private authority into the fixed local Keychain item;
|
||||
2. confirm battery/storage and select one K1 over BLE;
|
||||
3. run the exact response-gated bootstrap and attest activated FW 3.0.2;
|
||||
3. run the exact staged response-gated preparation and attest activated FW 3.0.2;
|
||||
4. confirm READY identity against DeviceInfo and review shadow metadata;
|
||||
5. send one START without retry and correlate its response;
|
||||
6. observe calibration and first point/pose/camera data;
|
||||
6. preserve the same control MQTT connection, issue the retained post-START
|
||||
reads and observe calibration plus first point/pose/camera data;
|
||||
7. send one STOP without retry and correlate its response;
|
||||
8. seal local evidence while accepting the bounded stream tail;
|
||||
9. wait for READY and steady green;
|
||||
|
||||
@@ -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 1–6. 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 13–14 about 24–25 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 1–6 follow connection, request 7 follows explicit workspace entry,
|
||||
requests 8–10 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 13–14 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 12–14 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
|
||||
1–14, 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.
|
||||
Reference in New Issue
Block a user