chore: rename repository to NODEDC MISSION CORE
This commit is contained in:
parent
8459bb03fb
commit
9225227421
|
|
@ -1,8 +1,9 @@
|
||||||
# Repository operating rules
|
# Repository operating rules
|
||||||
|
|
||||||
This repository investigates an owner-controlled XGRIDS/LixelKity K1 as a
|
NODEDC MISSION CORE is a vendor-neutral mission-control monorepo. Its first
|
||||||
black-box sensor. Preserve the device, the Mac, the working LAN, and raw
|
real device plugin investigates an owner-controlled XGRIDS/LixelKity K1 as a
|
||||||
evidence.
|
black-box sensor. Preserve the device, the host, the working LAN, raw evidence,
|
||||||
|
and the boundary between Mission Core and vendor-specific integration code.
|
||||||
|
|
||||||
## Non-negotiable safety boundaries
|
## Non-negotiable safety boundaries
|
||||||
|
|
||||||
|
|
|
||||||
44
README.md
44
README.md
|
|
@ -1,16 +1,22 @@
|
||||||
# NDC XGRIDS K1 Connector
|
# NODEDC MISSION CORE
|
||||||
|
|
||||||
Pre-production research project for connecting an owner-controlled
|
NODEDC MISSION CORE is the vendor-neutral control, observation, mission-planning,
|
||||||
XGRIDS/LixelKity K1 to a Mac without LixelGO, firmware changes, device opening,
|
recording, and integration platform for NODEDC autonomous systems. This
|
||||||
or speculative writes.
|
repository is the canonical early-stage monorepo: it contains the Mission Core
|
||||||
|
Control Station, the current local control plane, shared contracts as they are
|
||||||
|
extracted, and device plugins.
|
||||||
|
|
||||||
Current status: live proof completed on firmware 3.0.2. The Mac provisioned the
|
The first proven hardware vertical is the XGRIDS/LixelKity K1 plugin. On firmware
|
||||||
K1 onto an existing LAN without LixelGO, connected to its MQTT broker, captured
|
3.0.2 the host provisions the scanner onto an existing LAN without LixelGO,
|
||||||
the scan-correlated point-cloud and pose streams, and decoded both successfully.
|
connects to its MQTT broker, durably captures the raw stream, decodes point cloud
|
||||||
The repository also contains a local React control console, an automatic Rerun
|
and pose, and renders the real cloud plus trajectory through an embedded
|
||||||
gRPC bridge for the verified point-cloud and trajectory streams, and a
|
self-hosted Rerun Web Viewer. The former Foxglove bridge remains only as a
|
||||||
self-hosted Rerun Web Viewer embedded in that console. The former Foxglove
|
legacy regression module.
|
||||||
bridge remains only as a legacy regression module.
|
|
||||||
|
The repository is intentionally migrating in stages. The current `src/k1link`
|
||||||
|
package is the compatibility implementation of the first plugin path; vendor
|
||||||
|
transport and codecs will move behind `plugins/xgrids-k1` and the Mission Core
|
||||||
|
Plugin SDK without changing the verified wire protocol or raw evidence format.
|
||||||
|
|
||||||
The repository now contains one narrowly gated state-changing command:
|
The repository now contains one narrowly gated state-changing command:
|
||||||
`ble wifi-configure`. It accepts only the reviewed firmware-3 provisioning
|
`ble wifi-configure`. It accepts only the reviewed firmware-3 provisioning
|
||||||
|
|
@ -18,7 +24,7 @@ profile and requires explicit `--confirm-write`; the Wi-Fi password is collected
|
||||||
through a hidden local macOS dialog. MQTT capture and decoding are read-only.
|
through a hidden local macOS dialog. MQTT capture and decoding are read-only.
|
||||||
Nothing changes router settings, firmware or global Python packages.
|
Nothing changes router settings, firmware or global Python packages.
|
||||||
|
|
||||||
## Available stand
|
## Verified XGRIDS K1 stand
|
||||||
|
|
||||||
- one XGRIDS/LixelKity K1;
|
- one XGRIDS/LixelKity K1;
|
||||||
- one Apple Silicon MacBook running macOS;
|
- one Apple Silicon MacBook running macOS;
|
||||||
|
|
@ -51,15 +57,15 @@ This does not install Python packages globally and does not modify neighboring
|
||||||
repositories.
|
repositories.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /Users/dcconstructions/Downloads/mnt/NODEDC/NDC_xgrids-k1-connector
|
cd /Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE
|
||||||
uv sync --group dev
|
uv sync --group dev
|
||||||
uv run k1link doctor
|
uv run k1link doctor
|
||||||
uv run pytest
|
uv run pytest
|
||||||
```
|
```
|
||||||
|
|
||||||
## NODE.DC Control Station and visualization adapters
|
## Mission Core Control Station and visualization adapters
|
||||||
|
|
||||||
The browser application is now a universal NODE.DC Control Station rather than
|
The browser application is the universal Mission Core Control Station rather than
|
||||||
a K1-specific Foxglove launcher. Its fixed shell contains six architectural
|
a K1-specific Foxglove launcher. Its fixed shell contains six architectural
|
||||||
sections — Center, Fleet, Observation, Missions, Data and System — while the K1
|
sections — Center, Fleet, Observation, Missions, Data and System — while the K1
|
||||||
BLE/Wi-Fi/live workflow remains isolated as the first real device adapter.
|
BLE/Wi-Fi/live workflow remains isolated as the first real device adapter.
|
||||||
|
|
@ -69,7 +75,7 @@ repository root:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv sync --group dev
|
uv sync --group dev
|
||||||
cd apps/k1-viewer
|
cd apps/control-station
|
||||||
npm install
|
npm install
|
||||||
npm run typecheck
|
npm run typecheck
|
||||||
npm run build
|
npm run build
|
||||||
|
|
@ -86,7 +92,7 @@ Physical K1 scanning is still started and stopped by the verified double-click;
|
||||||
the connector publishes no modeling command.
|
the connector publishes no modeling command.
|
||||||
|
|
||||||
The Observation spatial workspace embeds the open-source Rerun Web Viewer
|
The Observation spatial workspace embeds the open-source Rerun Web Viewer
|
||||||
inside the NODE.DC shell. It can open a compatible RRD file over HTTP(S) or a
|
inside the Mission Core shell. It can open a compatible RRD file over HTTP(S) or a
|
||||||
Rerun gRPC/proxy source such as `rerun+http://127.0.0.1:9876/proxy`. It does not
|
Rerun gRPC/proxy source such as `rerun+http://127.0.0.1:9876/proxy`. It does not
|
||||||
use an external hosted viewer UI.
|
use an external hosted viewer UI.
|
||||||
|
|
||||||
|
|
@ -118,7 +124,7 @@ The old Foxglove implementation is retained only in
|
||||||
live/replay runtime does not start it or use TCP 8765. The
|
live/replay runtime does not start it or use TCP 8765. The
|
||||||
[live viewer runbook](docs/06_K1_LIVE_VIEWER.md) records the active Rerun path and
|
[live viewer runbook](docs/06_K1_LIVE_VIEWER.md) records the active Rerun path and
|
||||||
its timing/security boundaries; the frontend contract is documented in
|
its timing/security boundaries; the frontend contract is documented in
|
||||||
[`apps/k1-viewer/README.md`](apps/k1-viewer/README.md).
|
[`apps/control-station/README.md`](apps/control-station/README.md).
|
||||||
|
|
||||||
The FastAPI application and credential endpoint bind to loopback, but the Rerun
|
The FastAPI application and credential endpoint bind to loopback, but the Rerun
|
||||||
gRPC server currently binds TCP 9876 on all network interfaces even though its
|
gRPC server currently binds TCP 9876 on all network interfaces even though its
|
||||||
|
|
@ -170,6 +176,8 @@ present.
|
||||||
- [Reviewed BLE Wi-Fi profile](docs/04_K1_WIFI_PROVISIONING_PROFILE.md)
|
- [Reviewed BLE Wi-Fi profile](docs/04_K1_WIFI_PROVISIONING_PROFILE.md)
|
||||||
- [Verified MQTT stream profile](docs/05_K1_MQTT_STREAM_PROFILE.md)
|
- [Verified MQTT stream profile](docs/05_K1_MQTT_STREAM_PROFILE.md)
|
||||||
- [Live console and embedded Rerun runbook](docs/06_K1_LIVE_VIEWER.md)
|
- [Live console and embedded Rerun runbook](docs/06_K1_LIVE_VIEWER.md)
|
||||||
|
- [Mission Core monorepo and plugin boundary](docs/07_MISSION_CORE_MONOREPO.md)
|
||||||
|
- [Monorepo architecture decision](docs/adr/0002-mission-core-monorepo.md)
|
||||||
- [Redacted live lab report](docs/lab/001_K1_LIVE_MQTT_20260715.redacted.md)
|
- [Redacted live lab report](docs/lab/001_K1_LIVE_MQTT_20260715.redacted.md)
|
||||||
- [Session manifest schema](schemas/session-manifest.schema.json)
|
- [Session manifest schema](schemas/session-manifest.schema.json)
|
||||||
- [Reference input provenance](docs/reference/README.md)
|
- [Reference input provenance](docs/reference/README.md)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Mission Core applications
|
||||||
|
|
||||||
|
- `control-station/` — the current browser operator application.
|
||||||
|
|
||||||
|
Applications consume Mission Core contracts and capabilities. Device-specific
|
||||||
|
transport and codecs belong under `plugins/`, not inside application routing
|
||||||
|
or navigation.
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Пункт управления NODE.DC
|
# NODEDC MISSION CORE · Control Station
|
||||||
|
|
||||||
Универсальный браузерный пункт управления NODE.DC на React 19, TypeScript и
|
Универсальный браузерный пункт управления Mission Core на React 19, TypeScript и
|
||||||
Vite. Приложение задаёт общую операторскую оболочку для аппаратов, сенсоров,
|
Vite. Приложение задаёт общую операторскую оболочку для аппаратов, сенсоров,
|
||||||
наблюдения, миссий и записей. XGRIDS/LixelKity K1 является первым реальным
|
наблюдения, миссий и записей. XGRIDS/LixelKity K1 является первым реальным
|
||||||
device adapter, но структура интерфейса от него не зависит.
|
device adapter, но структура интерфейса от него не зависит.
|
||||||
|
|
@ -15,7 +15,7 @@ device adapter, но структура интерфейса от него не
|
||||||
|
|
||||||
| Контур | Состояние | Что это означает |
|
| Контур | Состояние | Что это означает |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| NODE.DC fixed shell | Реализован | Header, навигация по разделам, рабочая поверхность, окна и инспекторы работают в одном приложении. |
|
| Mission Core fixed shell | Реализован | Header, навигация по разделам, рабочая поверхность, окна и инспекторы работают в одном приложении. |
|
||||||
| Локальный control plane | Реализован | React получает состояние и выполняет операции через FastAPI REST и WebSocket на loopback. |
|
| Локальный control plane | Реализован | React получает состояние и выполняет операции через FastAPI REST и WebSocket на loopback. |
|
||||||
| K1 BLE → Wi-Fi | Реализован | Реальный BLE-поиск всех видимых устройств и одна подтверждённая provisioning-запись выбранному устройству. |
|
| K1 BLE → Wi-Fi | Реализован | Реальный BLE-поиск всех видимых устройств и одна подтверждённая provisioning-запись выбранному устройству. |
|
||||||
| K1 live/replay MQTT | Реализован | Read-only приём, raw-first сохранение, декодирование облака точек и позы, реальные метрики. |
|
| K1 live/replay MQTT | Реализован | Read-only приём, raw-first сохранение, декодирование облака точек и позы, реальные метрики. |
|
||||||
|
|
@ -40,9 +40,9 @@ K1 MQTT :1883, read-only
|
||||||
└── gRPC/proxy TCP 9876
|
└── gRPC/proxy TCP 9876
|
||||||
└── rerun_grpc_url в REST/WebSocket state
|
└── rerun_grpc_url в REST/WebSocket state
|
||||||
└── встроенный @rerun-io/web-viewer
|
└── встроенный @rerun-io/web-viewer
|
||||||
└── пространственная сцена NODE.DC
|
└── пространственная сцена Mission Core
|
||||||
|
|
||||||
React Control Station ←→ REST /api/* + WebSocket /api/events
|
Mission Core Control Station ←→ REST /api/* + WebSocket /api/events
|
||||||
FastAPI на 127.0.0.1:8000
|
FastAPI на 127.0.0.1:8000
|
||||||
CoreBluetooth + live/replay runtime
|
CoreBluetooth + live/replay runtime
|
||||||
```
|
```
|
||||||
|
|
@ -62,7 +62,7 @@ viewer остаются активны, а следующая сессия сб
|
||||||
Shell собран из локальных NODE.DC UI packages и сохраняет одну структуру для
|
Shell собран из локальных NODE.DC UI packages и сохраняет одну структуру для
|
||||||
всех функциональных модулей:
|
всех функциональных модулей:
|
||||||
|
|
||||||
1. `AppHeader` — марка NODE.DC, выбор архитектурного раздела и состояние
|
1. `AppHeader` — марка NODEDC MISSION CORE, выбор архитектурного раздела и состояние
|
||||||
локального backend.
|
локального backend.
|
||||||
2. `AdminNavigationPanel` — контекст аппарата и список рабочих поверхностей
|
2. `AdminNavigationPanel` — контекст аппарата и список рабочих поверхностей
|
||||||
выбранного раздела.
|
выбранного раздела.
|
||||||
|
|
@ -105,10 +105,10 @@ layout пока остаются интерфейсным контрактом.
|
||||||
Канонический путь от корня репозитория:
|
Канонический путь от корня репозитория:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /Users/dcconstructions/Downloads/mnt/NODEDC/NDC_xgrids-k1-connector
|
cd /Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE
|
||||||
uv sync --group dev
|
uv sync --group dev
|
||||||
|
|
||||||
cd apps/k1-viewer
|
cd apps/control-station
|
||||||
npm install
|
npm install
|
||||||
npm run typecheck
|
npm run typecheck
|
||||||
npm run build
|
npm run build
|
||||||
|
|
@ -125,7 +125,7 @@ Wi-Fi.
|
||||||
Для разработки интерфейса после запуска backend:
|
Для разработки интерфейса после запуска backend:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd apps/k1-viewer
|
cd apps/control-station
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -136,7 +136,7 @@ Vite слушает `http://127.0.0.1:5173` и проксирует `/api` и `/
|
||||||
|
|
||||||
## Операторский путь для текущего K1 adapter
|
## Операторский путь для текущего K1 adapter
|
||||||
|
|
||||||
1. Запустить `uv run k1link serve` и открыть Control Station.
|
1. Запустить `uv run k1link serve` и открыть Mission Core Control Station.
|
||||||
2. Выбрать **Парк → Локальное устройство**.
|
2. Выбрать **Парк → Локальное устройство**.
|
||||||
3. Включить K1, дождаться стабильного индикатора и подтвердить это в форме.
|
3. Включить K1, дождаться стабильного индикатора и подтвердить это в форме.
|
||||||
4. Нажать **Показать все BLE-устройства**. Интерфейс показывает полный результат
|
4. Нажать **Показать все BLE-устройства**. Интерфейс показывает полный результат
|
||||||
|
|
@ -230,7 +230,7 @@ Custom timeline, переключатель 2D/3D/карты, семантиче
|
||||||
|
|
||||||
## Safety и чувствительные данные
|
## Safety и чувствительные данные
|
||||||
|
|
||||||
- Control Station и credential endpoint доступны только на loopback.
|
- Mission Core Control Station и credential endpoint доступны только на loopback.
|
||||||
- Исключение: Rerun gRPC/proxy на TCP 9876 сейчас слушает все сетевые интерфейсы,
|
- Исключение: Rerun gRPC/proxy на TCP 9876 сейчас слушает все сетевые интерфейсы,
|
||||||
хотя автоматически возвращаемый URL содержит `127.0.0.1`. На нём нет
|
хотя автоматически возвращаемый URL содержит `127.0.0.1`. На нём нет
|
||||||
connector-level authentication или TLS. Этот порт допустим только в доверенной
|
connector-level authentication или TLS. Этот порт допустим только в доверенной
|
||||||
|
|
@ -250,7 +250,7 @@ Custom timeline, переключатель 2D/3D/карты, семантиче
|
||||||
доказанный timestamp сенсора K1 и не photon-to-screen latency.
|
доказанный timestamp сенсора K1 и не photon-to-screen latency.
|
||||||
- Панорамный камерный поток в наблюдавшихся MQTT report topics отсутствует;
|
- Панорамный камерный поток в наблюдавшихся MQTT report topics отсутствует;
|
||||||
текущая Rerun-сцена содержит только облако точек и позу/траекторию, а
|
текущая Rerun-сцена содержит только облако точек и позу/траекторию, а
|
||||||
операционные метрики отображаются внешней оболочкой Control Station.
|
операционные метрики отображаются внешней оболочкой Mission Core.
|
||||||
- `sessions/` игнорируется Git и может содержать адреса, идентификаторы,
|
- `sessions/` игнорируется Git и может содержать адреса, идентификаторы,
|
||||||
траекторию и карту помещения. В репозиторий попадают только redacted manifests
|
траекторию и карту помещения. В репозиторий попадают только redacted manifests
|
||||||
и безопасная документация.
|
и безопасная документация.
|
||||||
|
|
@ -5,10 +5,10 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="Пункт управления NODE.DC — наблюдение, данные и планирование миссий беспилотных аппаратов."
|
content="NODEDC MISSION CORE — наблюдение, данные и планирование миссий беспилотных аппаратов."
|
||||||
/>
|
/>
|
||||||
<meta name="theme-color" content="#08090b" />
|
<meta name="theme-color" content="#08090b" />
|
||||||
<title>NODE.DC · Пункт управления</title>
|
<title>NODEDC MISSION CORE</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "@nodedc/k1-viewer",
|
"name": "@nodedc/mission-core-control-station",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@nodedc/k1-viewer",
|
"name": "@nodedc/mission-core-control-station",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nodedc/tokens": "file:../../../NODEDC_DESIGN_GUIDELINE/packages/tokens",
|
"@nodedc/tokens": "file:../../../NODEDC_DESIGN_GUIDELINE/packages/tokens",
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "@nodedc/k1-viewer",
|
"name": "@nodedc/mission-core-control-station",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 322 B After Width: | Height: | Size: 322 B |
|
|
@ -254,11 +254,11 @@ export default function App() {
|
||||||
const header = (
|
const header = (
|
||||||
<AppHeader
|
<AppHeader
|
||||||
brand={<img src="/nodedc-logo.svg" alt="NODE.DC" />}
|
brand={<img src="/nodedc-logo.svg" alt="NODE.DC" />}
|
||||||
brandLabel="NODE.DC"
|
brandLabel="NODEDC MISSION CORE"
|
||||||
left={<span className="station-label">ПУНКТ УПРАВЛЕНИЯ</span>}
|
left={<span className="station-label">MISSION CORE</span>}
|
||||||
center={
|
center={
|
||||||
<>
|
<>
|
||||||
<HeaderWorkspace kind="mark" label="NODE.DC Пункт управления" imageUrl="/nodedc-mark.svg" />
|
<HeaderWorkspace kind="mark" label="Mission Core" imageUrl="/nodedc-mark.svg" />
|
||||||
<HeaderNavigation
|
<HeaderNavigation
|
||||||
label="Архитектурные блоки пункта управления"
|
label="Архитектурные блоки пункта управления"
|
||||||
value={activeRoot ?? undefined}
|
value={activeRoot ?? undefined}
|
||||||
|
|
@ -300,7 +300,7 @@ export default function App() {
|
||||||
}
|
}
|
||||||
navigation={currentRoot ? (
|
navigation={currentRoot ? (
|
||||||
<AdminNavigationPanel
|
<AdminNavigationPanel
|
||||||
eyebrow="NODE.DC"
|
eyebrow="MISSION CORE"
|
||||||
title={currentRoot.title}
|
title={currentRoot.title}
|
||||||
closeLabel={`Закрыть раздел «${currentRoot.label}»`}
|
closeLabel={`Закрыть раздел «${currentRoot.label}»`}
|
||||||
navigationLabel={`Рабочие поверхности раздела «${currentRoot.label}»`}
|
navigationLabel={`Рабочие поверхности раздела «${currentRoot.label}»`}
|
||||||
|
|
@ -24,8 +24,8 @@ export function LandingStage({
|
||||||
return (
|
return (
|
||||||
<section className="landing-stage" data-root={root?.id ?? "home"}>
|
<section className="landing-stage" data-root={root?.id ?? "home"}>
|
||||||
<div className="landing-stage__copy">
|
<div className="landing-stage__copy">
|
||||||
<span className="section-eyebrow">{root?.eyebrow ?? "NODE.DC / ПУНКТ УПРАВЛЕНИЯ"}</span>
|
<span className="section-eyebrow">{root?.eyebrow ?? "NODEDC / MISSION CORE"}</span>
|
||||||
<h1>{root?.title ?? "Пункт управления"}</h1>
|
<h1>{root?.title ?? "Mission Core"}</h1>
|
||||||
<p>
|
<p>
|
||||||
{root?.statement ??
|
{root?.statement ??
|
||||||
"Наблюдение, планирование и корректировка миссий в одной модульной рабочей области."}
|
"Наблюдение, планирование и корректировка миссий в одной модульной рабочей области."}
|
||||||
|
|
@ -30,7 +30,7 @@ Rerun gRPC/proxy on TCP 9876
|
||||||
+--> rerun_grpc_url in REST/WebSocket state
|
+--> rerun_grpc_url in REST/WebSocket state
|
||||||
|
|
|
|
||||||
v
|
v
|
||||||
self-hosted @rerun-io/web-viewer inside NODE.DC Control Station
|
self-hosted @rerun-io/web-viewer inside Mission Core Control Station
|
||||||
|
|
||||||
React console <-- REST + WebSocket state --> FastAPI on 127.0.0.1:8000
|
React console <-- REST + WebSocket state --> FastAPI on 127.0.0.1:8000
|
||||||
```
|
```
|
||||||
|
|
@ -52,7 +52,7 @@ Prerequisites are the repository-local Python environment and Node.js 20.19+ or
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv sync --group dev
|
uv sync --group dev
|
||||||
cd apps/k1-viewer
|
cd apps/control-station
|
||||||
npm install
|
npm install
|
||||||
npm run typecheck
|
npm run typecheck
|
||||||
npm run build
|
npm run build
|
||||||
|
|
@ -121,7 +121,7 @@ does not publish an application request or modeling command.
|
||||||
|
|
||||||
On the first live or replay session, `RerunBridge`:
|
On the first live or replay session, `RerunBridge`:
|
||||||
|
|
||||||
- creates an explicit `RecordingStream("nodedc_device_spatial")`;
|
- creates an explicit `RecordingStream("nodedc_mission_core_spatial")`;
|
||||||
- installs the default spatial blueprint;
|
- installs the default spatial blueprint;
|
||||||
- starts the gRPC/proxy server on TCP 9876 with a 512 MiB late-client buffer;
|
- starts the gRPC/proxy server on TCP 9876 with a 512 MiB late-client buffer;
|
||||||
- reports `rerun+http://127.0.0.1:9876/proxy` only after the server is ready;
|
- reports `rerun+http://127.0.0.1:9876/proxy` only after the server is ready;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
# NODEDC MISSION CORE monorepo
|
||||||
|
|
||||||
|
This document maps the renamed repository to the target Mission Core
|
||||||
|
architecture without claiming that unfinished package boundaries already
|
||||||
|
exist.
|
||||||
|
|
||||||
|
## Current layout
|
||||||
|
|
||||||
|
| Path | Current responsibility | Target responsibility |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `apps/control-station/` | React shell, device workflow, spatial scene | Vendor-neutral operator application |
|
||||||
|
| `src/k1link/web/` | Local FastAPI control plane and K1 session orchestration | Generic host APIs plus plugin supervisor |
|
||||||
|
| `src/k1link/viewer/` | Replay runtime and Rerun adapter | Canonical scene sink and presentation adapter |
|
||||||
|
| `src/k1link/ble/` | K1 BLE discovery and reviewed provisioning | `plugins/xgrids-k1` |
|
||||||
|
| `src/k1link/mqtt/` | Raw-first K1 MQTT capture | `plugins/xgrids-k1` behind EvidenceStore |
|
||||||
|
| `src/k1link/protocol/` | Firmware-scoped K1 codecs | `plugins/xgrids-k1` |
|
||||||
|
| `packages/plugin-sdk/` | Contract placeholder | Versioned manifests, capabilities, lifecycle, schemas |
|
||||||
|
| `plugins/xgrids-k1/` | Extraction boundary and documentation | Independently versioned device plugin |
|
||||||
|
|
||||||
|
## Extraction order
|
||||||
|
|
||||||
|
1. Define canonical PointCloud, Pose, DeviceStatus, RawEnvelope, and metrics
|
||||||
|
contracts in the Plugin SDK.
|
||||||
|
2. Make Rerun consume canonical frames rather than K1 MQTT topics.
|
||||||
|
3. Extract codecs and replay parity fixtures.
|
||||||
|
4. Extract raw capture with fault isolation between evidence and preview.
|
||||||
|
5. Extract BLE/Wi-Fi provisioning and MQTT into a least-privilege edge worker.
|
||||||
|
6. Replace K1-specific host routes and state with plugin/device-session APIs.
|
||||||
|
7. Drive the connection wizard from plugin capabilities and schemas.
|
||||||
|
8. Re-run native replay and the physical BLE → Wi-Fi → MQTT → scene acceptance.
|
||||||
|
|
||||||
|
## Invariants
|
||||||
|
|
||||||
|
- Raw evidence is durable before preview work.
|
||||||
|
- Mission Core starts when the XGRIDS plugin is absent or disabled.
|
||||||
|
- The plugin cannot add global navigation or arbitrary CSS.
|
||||||
|
- Vendor writes and commands require declared capabilities and operator gates.
|
||||||
|
- The visualization engine can be replaced without changing device plugins.
|
||||||
|
- Real captures and credentials remain outside Git.
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
# ADR 0002: NODEDC MISSION CORE monorepo
|
||||||
|
|
||||||
|
- Status: accepted
|
||||||
|
- Date: 2026-07-16
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The repository began as a focused XGRIDS/LixelKity K1 connector and then gained
|
||||||
|
a vendor-neutral control-station shell, local control plane, replay runtime, and
|
||||||
|
embedded spatial viewer. The K1 vertical is proven on real hardware, but its
|
||||||
|
names and implementation are still coupled to the host.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
The product, repository, and local root are named NODEDC MISSION CORE. The
|
||||||
|
canonical Git path is `SILVER/NODEDC_MISSION_CORE`, and the local checkout is
|
||||||
|
`NODEDC_MISSION_CORE`.
|
||||||
|
|
||||||
|
Mission Core remains one monorepo while the first plugin contract stabilizes:
|
||||||
|
|
||||||
|
```text
|
||||||
|
apps/control-station/ browser operator application
|
||||||
|
packages/plugin-sdk/ shared plugin contracts and host interfaces
|
||||||
|
plugins/xgrids-k1/ XGRIDS/LixelKity K1 device plugin
|
||||||
|
src/k1link/ transitional compatibility implementation
|
||||||
|
docs/ architecture, runbooks, ADRs, and redacted evidence
|
||||||
|
```
|
||||||
|
|
||||||
|
An independent plugin does not require an independent Git repository at this
|
||||||
|
stage. The XGRIDS plugin must have an explicit package/runtime boundary,
|
||||||
|
manifest, capabilities, tests, and no ownership of Mission Core navigation.
|
||||||
|
It can be split into another repository later without changing host contracts.
|
||||||
|
|
||||||
|
The Rerun integration is a replaceable presentation adapter. It is not the
|
||||||
|
Mission Core data bus, session database, or device protocol.
|
||||||
|
|
||||||
|
## Compatibility boundary
|
||||||
|
|
||||||
|
The rename does not alter these proven interfaces:
|
||||||
|
|
||||||
|
- Python import namespace and CLI `k1link`;
|
||||||
|
- native `.k1mqtt` framing and `K1MQTT` magic;
|
||||||
|
- provisioning profile `xgrids-k1-fw3-wifi-v1`;
|
||||||
|
- K1 MQTT topics and firmware-scoped protobuf/LZ4 codecs;
|
||||||
|
- current `k1_ip`, `K1Metrics`, and `useK1Console` compatibility fields;
|
||||||
|
- schema v1 `$id`, which remains an immutable legacy identifier.
|
||||||
|
|
||||||
|
Those names move or change only during the plugin-extraction milestone with
|
||||||
|
explicit migration and regression tests.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- Product branding, repository metadata, frontend application path, API title,
|
||||||
|
and Rerun recording identity use Mission Core naming now.
|
||||||
|
- The existing K1 implementation remains operational while contracts are
|
||||||
|
extracted incrementally.
|
||||||
|
- Core must eventually boot without the XGRIDS plugin.
|
||||||
|
- Plugin failure must not terminate the Mission Core host or raw evidence plane.
|
||||||
|
- A future repository split remains possible after Plugin SDK v1 is stable.
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Mission Core Plugin SDK
|
||||||
|
|
||||||
|
This directory reserves the versioned host/plugin contract. It is not yet a
|
||||||
|
published SDK and must not be treated as an implemented runtime.
|
||||||
|
|
||||||
|
The first contract will define:
|
||||||
|
|
||||||
|
- plugin manifest, version compatibility, firmware profiles, and permissions;
|
||||||
|
- discovery candidates and opaque device references;
|
||||||
|
- provisioning requests using secret references;
|
||||||
|
- device-session lifecycle and health;
|
||||||
|
- EvidenceStore handles and raw-artifact lineage;
|
||||||
|
- canonical PointCloud, Pose, DeviceStatus, and metrics envelopes;
|
||||||
|
- SceneSink and event interfaces;
|
||||||
|
- capability-driven UI contribution data without plugin-owned layout.
|
||||||
|
|
||||||
|
The XGRIDS K1 extraction is the first acceptance test. A synthetic reference
|
||||||
|
plugin will verify that no K1 names or protocol assumptions remain in core.
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
# XGRIDS / LixelKity K1 plugin
|
||||||
|
|
||||||
|
This directory is the target package boundary for the first Mission Core device
|
||||||
|
plugin. The verified implementation remains temporarily in `src/k1link` so the
|
||||||
|
real-device path stays operational during extraction.
|
||||||
|
|
||||||
|
The plugin owns:
|
||||||
|
|
||||||
|
- BLE discovery hints and K1 GATT metadata;
|
||||||
|
- the reviewed firmware-3 Wi-Fi provisioning profile;
|
||||||
|
- K1 LAN status and private-address validation;
|
||||||
|
- subscribe-only MQTT transport and report-topic allowlist;
|
||||||
|
- native `.k1mqtt` capture;
|
||||||
|
- firmware-scoped protobuf/LZ4 and legacy codecs;
|
||||||
|
- normalization of K1 point cloud, pose, status, health, and artifacts;
|
||||||
|
- K1-specific operator instructions and compatibility tests.
|
||||||
|
|
||||||
|
The plugin does not own:
|
||||||
|
|
||||||
|
- Mission Core navigation, fleet, missions, users, roles, or audit;
|
||||||
|
- the generic spatial scene or Rerun Web Viewer;
|
||||||
|
- platform storage, remote transport, or other devices.
|
||||||
|
|
||||||
|
Until extraction is complete, `src/k1link` is the compatibility source of
|
||||||
|
truth and every move into this package must preserve replay and real-device
|
||||||
|
acceptance.
|
||||||
|
|
@ -3,9 +3,9 @@ requires = ["hatchling>=1.27,<2"]
|
||||||
build-backend = "hatchling.build"
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "ndc-xgrids-k1-connector"
|
name = "nodedc-mission-core"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "macOS-first, evidence-led research tooling for an XGRIDS Lixel K1"
|
description = "NODEDC Mission Core monorepo for mission control, spatial observation, and device plugins"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12,<3.13"
|
requires-python = ">=3.12,<3.13"
|
||||||
license = { text = "Proprietary" }
|
license = { text = "Proprietary" }
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"$id": "https://git.dcserve.ru/SILVER/NDC_xgrids-k1-connector/schemas/session-manifest.schema.json",
|
"$id": "https://git.dcserve.ru/SILVER/NDC_xgrids-k1-connector/schemas/session-manifest.schema.json",
|
||||||
|
"$comment": "The legacy v1 schema identifier is intentionally immutable after the repository rename to NODEDC_MISSION_CORE.",
|
||||||
"title": "K1 laboratory session manifest",
|
"title": "K1 laboratory session manifest",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
"""NDC XGRIDS K1 connector research tooling."""
|
"""Mission Core runtime with the transitional XGRIDS K1 compatibility adapter."""
|
||||||
|
|
||||||
__version__ = "0.1.0"
|
__version__ = "0.1.0"
|
||||||
|
|
|
||||||
|
|
@ -208,15 +208,15 @@ def serve_console(
|
||||||
typer.Option(min=1024, max=65535, help="Loopback HTTP port for the local console."),
|
typer.Option(min=1024, max=65535, help="Loopback HTTP port for the local console."),
|
||||||
] = 8000,
|
] = 8000,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Serve the built K1 console and local-only control API on loopback."""
|
"""Serve the built Mission Core Control Station and loopback control API."""
|
||||||
frontend = Path(__file__).resolve().parents[2] / "apps" / "k1-viewer" / "dist"
|
frontend = Path(__file__).resolve().parents[2] / "apps" / "control-station" / "dist"
|
||||||
if not frontend.is_dir():
|
if not frontend.is_dir():
|
||||||
console.print(
|
console.print(
|
||||||
"[red]Frontend build is missing.[/red] Run npm install && npm run build "
|
"[red]Frontend build is missing.[/red] Run npm install && npm run build "
|
||||||
"inside apps/k1-viewer."
|
"inside apps/control-station."
|
||||||
)
|
)
|
||||||
raise typer.Exit(code=2)
|
raise typer.Exit(code=2)
|
||||||
console.print(f"K1 Live Console: http://127.0.0.1:{port}")
|
console.print(f"NODEDC MISSION CORE: http://127.0.0.1:{port}")
|
||||||
console.print("The credential endpoint is bound to this Mac only.")
|
console.print("The credential endpoint is bound to this Mac only.")
|
||||||
uvicorn.run(
|
uvicorn.run(
|
||||||
"k1link.web.app:app",
|
"k1link.web.app:app",
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ class FoxgloveBridge:
|
||||||
) -> None:
|
) -> None:
|
||||||
self.metrics = metrics or BridgeMetrics()
|
self.metrics = metrics or BridgeMetrics()
|
||||||
self._server = foxglove.start_server(
|
self._server = foxglove.start_server(
|
||||||
name="NODE.DC K1 live bridge",
|
name="Mission Core K1 legacy bridge",
|
||||||
host=host,
|
host=host,
|
||||||
port=port,
|
port=port,
|
||||||
message_backlog_size=32,
|
message_backlog_size=32,
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ class RerunBridge:
|
||||||
self._settings_provider = settings_provider or RerunSceneSettings
|
self._settings_provider = settings_provider or RerunSceneSettings
|
||||||
self._settings = self._settings_provider()
|
self._settings = self._settings_provider()
|
||||||
self._recording = (recording_factory or rr.RecordingStream)(
|
self._recording = (recording_factory or rr.RecordingStream)(
|
||||||
"nodedc_device_spatial"
|
"nodedc_mission_core_spatial"
|
||||||
)
|
)
|
||||||
blueprint = _blueprint(self._settings)
|
blueprint = _blueprint(self._settings)
|
||||||
self._url = self._recording.serve_grpc(
|
self._url = self._recording.serve_grpc(
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
"""Local-only control API for the K1 live console."""
|
"""Local Mission Core control plane with the transitional XGRIDS adapter."""
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,7 @@ async def app_lifespan(_: FastAPI) -> AsyncIterator[None]:
|
||||||
|
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
title="NODE.DC Device Control API",
|
title="NODEDC Mission Core API",
|
||||||
version=__version__,
|
version=__version__,
|
||||||
docs_url="/api/docs",
|
docs_url="/api/docs",
|
||||||
redoc_url=None,
|
redoc_url=None,
|
||||||
|
|
@ -275,7 +275,7 @@ def health() -> dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
"ok": True,
|
"ok": True,
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
"service": "k1-live-console",
|
"service": "mission-core-control-plane",
|
||||||
"version": __version__,
|
"version": __version__,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,7 +341,7 @@ async def events(websocket: WebSocket) -> None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
frontend_dist = REPOSITORY_ROOT / "apps" / "k1-viewer" / "dist"
|
frontend_dist = REPOSITORY_ROOT / "apps" / "control-station" / "dist"
|
||||||
if frontend_dist.is_dir():
|
if frontend_dist.is_dir():
|
||||||
app.mount("/", StaticFiles(directory=frontend_dist, html=True), name="frontend")
|
app.mount("/", StaticFiles(directory=frontend_dist, html=True), name="frontend")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue