From 1995dfdf6873c3537ce290ab686024431d39943f Mon Sep 17 00:00:00 2001 From: DCCONSTRUCTIONS Date: Fri, 24 Jul 2026 20:47:08 +0300 Subject: [PATCH] docs(simulation): accept S1C live worker --- README.md | 42 +++++- docs/01_IMPLEMENTATION_PLAN.md | 24 ++-- docs/12_SIMULATION_POLYGON_PRODUCT_AND_SRS.md | 26 ++++ ...ibuted-product-edge-and-worker-topology.md | 11 +- docs/runbooks/SIM_S1C_LIVE_WORKER.md | 130 ++++++++++++++++++ 5 files changed, 217 insertions(+), 16 deletions(-) create mode 100644 docs/runbooks/SIM_S1C_LIVE_WORKER.md diff --git a/README.md b/README.md index b894c4b..bedcd20 100644 --- a/README.md +++ b/README.md @@ -172,11 +172,36 @@ metadata and the virtual-only authority boundary. Live pause/resume/step/reset, canonical telemetry, PX4 command mapping, watchdog/failsafe evidence and the top-level Polygon control surface remain gated. -Configure a Mission Core backend that can read the accepted D repository and -open the direct route: +S1C commit `b7ccca3` adds the first registered live-worker vertical without +collapsing that boundary. An unprivileged worker agent owns the existing +application service and providers inside a fresh loopback-only network +namespace. Mission Core reaches it through a mode-`0600` Unix socket; React +reaches only same-origin Polygon API routes. The live browser panel can +start/stop the stock rover, show worker/run/provider status and render a bounded +top-down ENU trajectory from Gazebo dynamic-pose ground truth. That pose is +explicitly `diagnostic`, not accepted PX4/ROS 2 telemetry. + +The exact D-only generation passed 21 target tests and a real UI-driven run +`s1c-b7ccca3-20260724t174030z-8e46b3`: both providers reached readiness, the +browser received live `VehicleState`, the run reached `completed` after +52.836 seconds of Gazebo time, and shutdown left no PX4/Gazebo/XRCE process +residue. The run contained zero commands, so this result does not yet prove +rover motion, PX4 command delivery, watchdog/failsafe behavior, navigation or +safety acceptance. + +Start the worker from the exact immutable D source generation: + +```bash +sudo simulation/s1/worker-agent.sh +``` + +Then configure the Mission Core backend and open the direct route: ```bash export MISSIONCORE_POLYGON_RUNS_ROOT=/mnt/d/NDC_MISSIONCORE/simulation/artifacts/s1/runs +export MISSIONCORE_POLYGON_WORKER_SOCKET=/run/missioncore-sim/worker.sock +export MISSIONCORE_POLYGON_WORKER_CONTROL=internal-virtual-only +export MISSIONCORE_COMMIT= uv run uvicorn k1link.web.app:app --host 127.0.0.1 --port 8765 ``` @@ -184,15 +209,18 @@ uv run uvicorn k1link.web.app:app --host 127.0.0.1 --port 8765 http://127.0.0.1:8765/?workspace=polygon-run&run= ``` -The API provides `GET /api/v1/polygon/runs` and -`GET /api/v1/polygon/runs/{run-id}` only. Missing configuration returns `503`; -invalid/corrupt evidence fails closed. The browser receives no D root, artifact -bytes, command payloads or PX4/process-lifecycle operation. +The archive API remains GET-only. The worker API adds status/live GETs and +explicit start/stop POSTs; POSTs remain `403` unless the backend has the +`internal-virtual-only` gate and an exact commit. Missing configuration, +transport drift and corrupt evidence fail closed. The browser receives no Unix +socket, D root, artifact bytes, PX4 endpoint or direct provider command. See the [Polygon product/SRS](docs/12_SIMULATION_POLYGON_PRODUCT_AND_SRS.md), [ADR 0015](docs/adr/0015-simulation-polygon-qualification-boundary.md), [ADR 0016](docs/adr/0016-distributed-product-edge-and-worker-topology.md) and the -[SIM S0 worker runbook](docs/runbooks/SIM_S0_AI_WORKER.md). +[SIM S0 worker runbook](docs/runbooks/SIM_S0_AI_WORKER.md). The live-worker +launch and acceptance procedure is in +[SIM S1C live-worker runbook](docs/runbooks/SIM_S1C_LIVE_WORKER.md). Mission Core remains a distributed browser product rather than a platform-specific desktop executable. React runs in the operator browser; diff --git a/docs/01_IMPLEMENTATION_PLAN.md b/docs/01_IMPLEMENTATION_PLAN.md index 712fcec..6e7646b 100644 --- a/docs/01_IMPLEMENTATION_PLAN.md +++ b/docs/01_IMPLEMENTATION_PLAN.md @@ -24,7 +24,7 @@ Each gate produces evidence and an explicit GO, PAUSE or BLOCKED result. | 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 | GO (physical staged cycle) — after fixing the PCAP-proven `sint64` time field, one explicit UI launch completed all 14 canonical operations on one control session, reached live `SCANNING + project + init_ready`, displayed real points, then one explicit STOP returned K1 to unbound `READY`. No retry or fallback command was sent. Native-project reuse through LixelGO/USB remains an independent verification | | Stage 8 product storage | PAUSE — retention, replication, encryption, capacity monitoring and long-run browser/WASM stress remain deployment gates | -| Simulation Polygon | SIM S0 GO; S1A complete; S1B real-provider lifecycle PASS; UI-0 internal read-only run view PASS — exact commit `6cb1495` passed 25 target tests and one D-only loopback stock-Ackermann run. Mission Core admitted world/startup/DDS health, persisted eight events, sent zero commands and stopped both PGIDs with zero residue. The Control Station now reads that canonical journal through GET-only Polygon API routes and a direct hidden workspace; visual QA opened the real accepted run. Pause/resume/step/reset, PX4 command delivery, canonical telemetry/frames, watchdog/failsafe, navigation/safety acceptance and real actuator authority remain absent; top-level Polygon remains gated | +| Simulation Polygon | SIM S0 GO; S1A complete; S1B lifecycle PASS; S1C registered live worker/UI PASS — exact commit `b7ccca3` passed 21 focused target tests and a UI-driven D-only PX4/Gazebo run. Mission Core registered the loopback-only unprivileged worker through a private Unix socket, rendered diagnostic ENU `VehicleState`, persisted eight events and stopped both provider groups with zero residue. The run sent zero commands; PX4 command delivery/motion, canonical PX4/ROS 2 telemetry, pause/step/reset, watchdog/failsafe, navigation/safety acceptance, auth/RBAC and real actuator authority remain absent; top-level Polygon remains gated | USB project copying remains optional ground truth rather than a blocker for the now-verified network path. Owner-operated LixelGO traffic verifies the MQTT @@ -160,9 +160,15 @@ exact-profile/D-only worker guard, health-gated real provider specs and deterministic POSIX PGID supervision. Exact generation `6cb1495` passed on `MissionCore-Sim`: Micro XRCE-DDS Agent and PX4/Gazebo stock rover ran inside a fresh loopback-only namespace, the run reached `completed`, and both provider -groups stopped without residue. Live world control, PX4 command delivery, -heartbeat/watchdog execution and captured failsafe outcomes remain the next S1 -increments. +groups stopped without residue. S1C commit `b7ccca3` adds a persistent +unprivileged worker agent in the same isolation boundary, a bounded Unix-socket +gateway, an explicit `internal-virtual-only` backend gate and a browser-native +live panel. The exact D-only generation passed 21 target tests and one +UI-driven provider run with diagnostic Gazebo `VehicleState`, eight persisted +lifecycle events, terminal `completed` and zero process residue. Its +zero-command stationary rover does not close PX4 command delivery, canonical +PX4/ROS 2 telemetry, pause/step/reset, heartbeat/watchdog or failsafe checkers; +these remain the next S1 increments. UI-0 now consumes the same append-only run repository through `GET /api/v1/polygon/runs` and @@ -172,10 +178,12 @@ write transition. The Control Station opens the internal `polygon-run-internal` workspace only for the direct `?workspace=polygon-run[&run=]` route; it is filtered out of System navigation and adds no seventh top-level section. Browser QA loaded the accepted -real run with eight events, four provider pins, zero commands and the unchanged -virtual-only authority boundary. A shared operator-facing deployment still -requires a reviewed read-only D mount/source configuration; UI-0 does not use -SSH as a product data plane. +archive and the S1C live worker. The hidden UI-1 panel shows +worker/run/provider status, sim time, ENU/FLU pose and a bounded 2D trajectory. +Start/stop stays behind the backend gate and reaches the worker through a local +Unix socket; SSH remains qualification bootstrap, never the product data plane. +A shared operator-facing deployment still requires authentication/RBAC, +service supervision and an accepted routed worker transport. Mission Core remains a distributed web product. React is served by a long-lived Gateway/API and renders canonical state through browser-native components. diff --git a/docs/12_SIMULATION_POLYGON_PRODUCT_AND_SRS.md b/docs/12_SIMULATION_POLYGON_PRODUCT_AND_SRS.md index 2c59e50..cc4e867 100644 --- a/docs/12_SIMULATION_POLYGON_PRODUCT_AND_SRS.md +++ b/docs/12_SIMULATION_POLYGON_PRODUCT_AND_SRS.md @@ -73,6 +73,18 @@ Polygon is now a parallel product branch. As of this document: over GET-only Polygon API routes. Browser QA loaded the real accepted S1B journal and displayed its four provider pins, eight events, zero commands and unchanged virtual-only authority boundary; +- S1C exact code generation `b7ccca3` adds a persistent, unprivileged + Simulation Worker agent in a fresh loopback-only namespace, a bounded + Unix-socket Mission Core gateway and an explicit `internal-virtual-only` + lifecycle gate; +- the hidden UI-1 live panel starts/stops the stock rover through Mission Core, + polls canonical worker state and renders a bounded ENU trajectory from + Gazebo dynamic-pose ground truth. The signal is marked `diagnostic`; +- the UI-driven target run + `s1c-b7ccca3-20260724t174030z-8e46b3` reached `completed` with eight + persisted events, 52.836 seconds of Gazebo time and zero provider residue; + it contained zero commands and therefore does not prove rover motion or PX4 + command delivery; - `actuator_authority=false`; - `navigation_or_safety_accepted=false`. @@ -672,6 +684,20 @@ restart-safe PID/start-token reconciliation, live pause/resume/step/reset, canonical VehicleState, frame conversion, rover command mapping, watchdog/failsafe cases, repeatability or S1 as a whole. +S1C commit `b7ccca3` accepts the next placement/presentation slice only. A +persistent worker agent runs unprivileged in a new loopback-only namespace and +is registered to Mission Core through a private Unix socket. The browser uses +same-origin APIs for worker status, explicit virtual-only start/stop and a +bounded `missioncore.vehicle-state/v1` view. Exact target source archive +SHA-256 is +`fc3195dbffef270f9669c194cf90e3fe4b62e113a5a7b74af89caa123b601ccd`; +the xattr-free Control Station build archive SHA-256 is +`76b687d12a7675275dfae8ebe3d806d3725240182136108c9bd01f0e8e364df6`. +The first UI-driven run completed cleanly with 52.836 seconds of Gazebo time +and no provider residue. Its `VehicleState` is Gazebo ground truth marked +`diagnostic`; PX4/ROS 2 canonical telemetry and command-induced rover motion +remain open. + ### S2 - Gazebo LiDAR/odometry feed the ROS 2/Nav2 baseline. diff --git a/docs/adr/0016-distributed-product-edge-and-worker-topology.md b/docs/adr/0016-distributed-product-edge-and-worker-topology.md index 4b3b948..e4fe6d8 100644 --- a/docs/adr/0016-distributed-product-edge-and-worker-topology.md +++ b/docs/adr/0016-distributed-product-edge-and-worker-topology.md @@ -126,6 +126,16 @@ The current `MissionCore-Sim` WSL2 distribution on the D drive is this topology's first qualified worker. Its native Gazebo window is local diagnostics; the product view remains browser-native. +The first implemented registration slice is S1C commit `b7ccca3`. Mission Core +and the worker share only a private mode-`0600` Unix socket in the WSL mount +namespace. PX4, Gazebo and Micro XRCE-DDS stay inside the worker's +loopback-only network namespace and run as the unprivileged `missioncore` +identity. Run artifacts and provider logs remain under the admitted D-only +roots. The React client calls same-origin Mission Core endpoints and never +receives the socket path or a provider endpoint. Remote/routed worker +registration is intentionally not inferred from this local laboratory +transport; it requires an authenticated contract of its own. + ### Connected field vehicle ```text @@ -169,4 +179,3 @@ application. It is the review side of the same distributed system. - Field hardware, storage budgets, network-loss policy, physical e-stop, operator takeover and real actuator authority still require separate acceptance. - diff --git a/docs/runbooks/SIM_S1C_LIVE_WORKER.md b/docs/runbooks/SIM_S1C_LIVE_WORKER.md new file mode 100644 index 0000000..b187acb --- /dev/null +++ b/docs/runbooks/SIM_S1C_LIVE_WORKER.md @@ -0,0 +1,130 @@ +# SIM S1C live-worker runbook + +## Scope + +This runbook starts the first browser-visible stock Ackermann rover through the +Mission Core control plane. It accepts only a virtual PX4/Gazebo run. It does +not admit a physical vehicle, direct actuator setpoints, navigation or safety. + +Runtime placement: + +```text +React Control Station + -> same-origin Mission Core Polygon API + -> mode-0600 Unix socket + -> unprivileged Simulation Worker agent + -> loopback-only network namespace + -> Micro XRCE-DDS Agent + PX4 SITL + Gazebo Harmonic +``` + +The Unix socket is ephemeral runtime coordination. Source, run journals, +provider logs and qualification artifacts remain under +`/mnt/d/NDC_MISSIONCORE/simulation`. + +## Preconditions + +- use the dedicated `MissionCore-Sim` WSL distribution; +- stage an immutable Git archive below the reviewed D root; +- verify its SHA-256 against the source artifact; +- use an exact 40-character Mission Core commit; +- confirm no PX4, Gazebo or Micro XRCE-DDS provider residue exists; +- keep `actuator_authority=false`; +- do not add a routed NIC to the worker namespace. + +## Start worker agent + +From the exact staged source generation: + +```bash +sudo simulation/s1/worker-agent.sh +``` + +The wrapper creates `/run/missioncore-sim` as a private runtime directory, +enters a fresh network namespace, raises only loopback and drops to the +`missioncore` user before importing product code. + +Expected status through the backend gateway: + +```json +{ + "schema_version": "missioncore.simulation-worker-status/v1", + "worker_id": "mission-gpu-s1", + "transport": "unix", + "mode": "simulation", + "available": true, + "control_available": true, + "active_run_id": null, + "run_state": null +} +``` + +## Start Mission Core + +```bash +export MISSIONCORE_POLYGON_RUNS_ROOT=/mnt/d/NDC_MISSIONCORE/simulation/artifacts/s1/runs +export MISSIONCORE_POLYGON_WORKER_SOCKET=/run/missioncore-sim/worker.sock +export MISSIONCORE_POLYGON_WORKER_CONTROL=internal-virtual-only +export MISSIONCORE_COMMIT= +uv run uvicorn k1link.web.app:app --host 127.0.0.1 --port 8765 +``` + +Open: + +```text +http://127.0.0.1:8765/?workspace=polygon-run +``` + +The live panel must show `Worker готов`. Start/stop calls require an +`Idempotency-Key`; the React client generates one per operator intent. Removing +the `internal-virtual-only` environment gate must leave status visible while +disabling lifecycle actions. + +## Live-state contract + +The first S1C live sample comes from: + +```text +/world/rover/dynamic_pose/info +``` + +It is published to the browser as `missioncore.vehicle-state/v1` with: + +- `frame_id=map_enu`; +- `child_frame_id=base_link_flu`; +- integer Gazebo simulation time; +- bounded position and quaternion; +- `signal=ground-truth`; +- `quality=diagnostic`; +- `scope=virtual-only`; +- no navigation or safety acceptance. + +This signal proves live presentation and frame naming only. It is not the +accepted PX4/ROS 2 telemetry path. + +## Acceptance checklist + +- [ ] exact source commit and source/build SHA-256 recorded; +- [ ] focused target tests pass from the same staged generation; +- [ ] worker status reports loopback-only, unprivileged and D-only boundaries; +- [ ] browser start creates one new immutable qualification run; +- [ ] status traverses `starting -> running`; +- [ ] both provider IDs appear only after readiness; +- [ ] live samples advance in Gazebo time; +- [ ] React shows run ID, sim time, ENU pose and provider list; +- [ ] archive remains path-free and command content is not exposed; +- [ ] browser stop reaches terminal `completed`; +- [ ] stop records `operator-stop-clean`; +- [ ] PX4, Gazebo and Micro XRCE-DDS leave no process residue; +- [ ] command count remains zero until the command-delivery checker is accepted. + +## Failure handling + +- A missing socket returns unavailable status; it does not fall back to PX4. +- Start/stop is `403` without the explicit backend control gate. +- Commit drift is rejected before provider start. +- A malformed or oversized worker message fails the gateway contract. +- Provider readiness failure seals the run as failed and triggers supervised + cleanup. +- Agent termination aborts an active run and stops owned provider groups. +- Agent restart reconciles an interrupted journal as failed; restart-safe + cross-process PID ownership remains a separate open checker.