feat(k1): wire canonical control session to UI

This commit is contained in:
DCCONSTRUCTIONS
2026-07-18 17:53:55 +03:00
parent 36f0c93d2a
commit 7b7b5d6cad
24 changed files with 1591 additions and 184 deletions
+1 -1
View File
@@ -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 (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 |
| K1 application control | OPERATOR ACCEPTANCE READY — the failed collapsed path and standalone START/STOP remain disabled. Plugin v0.5.0 installs one continuous control-session owner behind separate connection, workspace, project, START, STOP and steady-green UI actions. No wall-clock transition, automatic retry, navigation-triggered command or repository-test equipment I/O exists. A full operator-run physical cycle and native-project verification remain open |
| 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
+5 -4
View File
@@ -260,7 +260,7 @@ 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
replacement is an operator-driven acceptance 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
@@ -270,9 +270,10 @@ 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 15120-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.
START or STOP confirmation, not at connection time. Plugin v0.5.0 now exposes
this path through separate plugin-owned UI actions. Repository tests use only
in-memory transports; physical execution occurs only from an explicit operator
click against an already selected direct-LAN K1.
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
+28 -27
View File
@@ -115,44 +115,45 @@ directly and use their sibling metadata receive timestamps when present.
complete visible-device list.
4. Enter the existing router SSID/password and explicitly authorize the reviewed
provisioning write. The backend does not retry the write automatically.
5. Enter the required project name. Mission Core NFKC-normalizes and trims it,
rejects control/surrogate characters or more than 96 characters, and stores
it as local display metadata rather than a path. The read-only profile does
not send it to K1.
6. When K1 reports a non-AP private address, choose **Подготовить локальный
приём данных**. The stronger “initiate device work” wording appears only for
a future profile that actually authorizes a vendor write.
7. Wait until the UI reports that the local Rerun bridge is ready. No manual
viewer URL is needed.
8. Open **Наблюдение → Пространственная сцена**. The K1 plugin's optional scene
block shows the local preparation/acquisition phase and stop action.
9. Double-click the physical K1 button to start scanning. Real point frames and
pose/trajectory updates then appear in the embedded viewport.
5. Confirm operator presence, closed LixelGO, storage/power and steady green;
choose **Подключить управление K1**. This emits only connection operations
16 and then waits indefinitely for the next UI action.
6. Choose **Открыть рабочее пространство K1** for operation 7.
7. Enter the required project name and choose **Сохранить проект и подготовить
локальный приём**. Mission Core normalizes it, prepares evidence reception
and releases only operations 810; the name itself is not sent yet.
8. After the project step is ready, choose **Запустить сканирование K1** once.
The project name is carried by canonical START. Mission Core opens
**Наблюдение → Пространственная сцена** and shows calibration while the same
control socket waits for `SCANNING + project + init_ready`.
9. Real point frames and pose/trajectory updates then appear in the embedded
viewport. Do not use the physical button or open LixelGO during this cycle.
10. When K1 emits `ModelingReport`, the same plugin block shows its current scan
time, route distance and speed. These are device reports, not values inferred
from a browser timer or accumulated across a device counter reset.
11. Double-click K1 again to stop physical scanning and wait for steady green,
then choose **Остановить локальный приём** in the scene or device workflow
so capture, camera archive and summaries are finalized. That UI action does
not stop K1 on the active profile.
11. Choose **Остановить устройство и запись** in the scene. The
plugin-commanded path emits one canonical STOP on the original socket,
waits for live unbound READY, and asks the operator to confirm the constant
green indicator before capture, camera archive and summaries are finalized.
Each new live run creates a direct child below `MISSIONCORE_EVIDENCE_DIR`, or
`.runtime/mission-core/evidence/sessions/` by default, with raw MQTT frames,
per-message metadata and a hash summary. Repository-level
`sessions/*_viewer_live` is legacy import-only evidence and is never selected by
the current writer. The connector subscribes to the fixed report-topic
allowlist and does not publish an application request or modeling command.
the current writer. The data connector remains subscribe-only. Application
requests are isolated in the separate canonical control-session owner and can
be emitted only by explicit staged UI actions.
The recovered command substrate is intentionally inert. It byte-matches the ten
The recovered command substrate byte-matches the ten
observed pre-START requests plus START/STOP, correlates DeviceInfo and modeling
responses, and classifies live device states without importing MQTT or
publishing anything. One private application-level OpenAPI authority is kept
responses, and classifies live device states before any command transition. One
private application-level OpenAPI authority is kept
separate from the transient vendor ID/serial returned by the BLE-selected K1.
The fixed Keychain loader, bounded execution lease and dormant facade
orchestrator now exist. No emission method or live MQTT sink is installed, and
an acceptance-only transport exists outside the facade. Keychain provisioning,
physical START/STOP and durable save completion remain open, so
`vendor_writes_enabled` is false and the physical-button workflow is canonical.
The fixed Keychain loader and dormant shadow coordinator remain available for
inspection. Plugin v0.5.0 additionally installs a continuous interactive MQTT
owner: operations 16 at connection, 7 at workspace entry, 810 at project
preparation, then separately permitted START and STOP. Physical START/STOP and
durable native-project completion still require operator acceptance.
## Automatic Rerun source and lifecycle
+10 -11
View File
@@ -138,21 +138,20 @@ after explicit operator attestation of firmware `3.0.2` and direct-LAN topology,
and records the basis as `operator-attested`. That claim is not device-derived
proof. The profile independently records observation, decode, replay,
physical-verification and write evidence. Loading it cannot authorize a
transport mutation. Application-command publishing remains disabled; the
separately reviewed BLE Wi-Fi provisioning write retains its own explicit
operator gate.
transport mutation. BLE Wi-Fi provisioning and application control retain
separate explicit operator gates.
An exact but inert K1 application-control substrate now lives inside the vendor
An exact K1 application-control substrate now lives inside the vendor
plugin. It byte-matches the retained ten-request pre-START dialogue plus
START/STOP, correlates live DeviceInfo/modeling responses and maps bounded
device-status values into an observation-only state machine. The OpenAPI value
device-status values into a fail-closed state machine. The OpenAPI value
is one private application-level authority; vendor ID and serial come from the
BLE-selected live K1 and are cross-checked against status. No MQTT publisher
exists. A fixed Keychain loader, bounded lease and dormant facade orchestrator
are present, but there is no emission method or live MQTT sink. Keychain item
provisioning and stable-artifact proof after STOP remain unresolved. A separate
acceptance-only transport is not imported by the facade, so
`vendor_writes_enabled=false` remains authoritative.
BLE-selected live K1 and are cross-checked against status. Plugin v0.5.0 owns a
single interactive MQTT session from connection through STOP/standby, with one
explicit UI action per recorded lifecycle boundary and no automatic retry. A
fixed Keychain loader and dormant shadow coordinator remain present. Stable
physical proof after STOP remains unresolved; write capability is exposed only
while that interactive socket owner is active.
## Semantic lifecycle
@@ -66,13 +66,16 @@ performs no implicit stop.
K1 project names are required, NFKC-normalized and trimmed, rejected for control
or surrogate characters or more than 96 Unicode characters, and sent to the
backend as local display metadata. The active profile has
`vendor_writes_enabled=false`, so its
backend as local display metadata. At the time of this ADR the active profile
had `vendor_writes_enabled=false`, so its
buttons and scene control say that they prepare/stop local reception. Before an
acquisition exists, device-start wording is gated by active-control capability;
after start, calibration/device-stop wording additionally requires a
plugin-commanded acquisition mode.
The application-control portion is superseded by ADR 0012 and plugin v0.5.0;
the plugin ownership and host-boundary decisions remain unchanged.
Plugin CSS is imported with the contribution and scoped below
`.xgrids-k1-plugin`. A plugin cannot add global navigation, route ownership or
unscoped global selectors.
@@ -110,8 +110,8 @@ shadow arm/disarm/state actions and redacted snapshots. The coordinator has no
request-emission method and the installed sink is explicitly uninstalled; this
runtime wiring does not widen write authority.
`application_mqtt.py` and `application_acceptance.py` provide the next, still
uninstalled physical-acceptance boundary. The MQTT type repeats the retained
`application_mqtt.py` and `application_acceptance.py` provide the reviewed
physical-acceptance boundary. The MQTT type repeats the retained
3.1.1 session (`clean_session=false`, keepalive 60), subscribes only to exact
known response topics, admits only reviewed request topics and QoS2/retain-false
envelopes, and consumes explicit bootstrap ordinals/modeling actions before the
@@ -134,8 +134,18 @@ 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.
connection time.
Plugin v0.5.0 installs this boundary through
`application_session.py`. One background owner is the only thread allowed to
touch the control MQTT client. REST/UI actions release exactly one checkpoint:
session open (16), workspace entry (7), project preparation (810), START, STOP
and steady-green confirmation. Preparing local reception happens before the
START event is released. After STOP, local capture remains owned until live
unbound READY and explicit visual confirmation. Page close, model switching,
polling and service state reads cannot emit START/STOP; model switching is
blocked while the socket is open. Repository tests replace the transport with
in-memory fakes and perform no equipment I/O.
`MacOSKeychainApplicationAuthorityProvisioner` invokes Apple's interactive
`security add-generic-password ... -w` prompt with `-w` last. The private value