From 4d661967ae842343c66434bf4b2a19f10bb625bb Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 11 Jun 2026 07:58:26 +0100 Subject: [PATCH] Route Move light ownership through Muninn --- docs/implementation-plan.md | 15 +++++++++------ notes/current-system-map.md | 20 +++++++++++++------- scripts/start-nightwing-move-tracking.ps1 | 14 +++++++------- state/evidence.jsonl | 1 + state/map.yaml | 4 ++++ tools/nightwing_typed_witness_publisher.py | 4 ++++ 6 files changed, 38 insertions(+), 20 deletions(-) diff --git a/docs/implementation-plan.md b/docs/implementation-plan.md index 966da8d..f3c69db 100644 --- a/docs/implementation-plan.md +++ b/docs/implementation-plan.md @@ -41,15 +41,18 @@ a named invariant that the native runtime cannot protect yet. schema projection, not pose capture or Mimir fusion. - `scripts/start-nightwing-move-tracking.ps1` is the narrow live Nightwing bring-up path: it starts the `/eve/periwinkle` receiver/recorder on Starfire, - stages the Nightwing Eye/Move Python worker, lights configured USB Moves via - HID report `0x06`, and publishes `mimir.psmove_light_state.v1` plus + stages the Nightwing Eye/Move Python worker, keeps a heartbeat for field + liveness, and publishes `mimir.psmove_light_state.v1` plus `mimir.move_controller_observation_state.v1` blob observations from both PS3 Eyes. The blob stream is optical witness evidence for later pose fusion, not the final 6DoF pose owner. -- `scripts/start-starfire-move-light.ps1` is the Starfire-local USB Move light - owner. It launches `Mimir.PsMoveProbe` in steady hold mode so the locally - attached `VID_054C/PID_03D5` Move sphere stays lit for calibration/tracking - receipts. +- Structured PS Move light pulses are Muninn output commands. Mimir publishes + `muninn.move_light_command.v1` over CultNet/CultMesh to the Muninn daemon on + the host that owns the USB-attached Move. Muninn writes PS Move HID report + `0x06` locally and updates command state/receipt. + `scripts/start-starfire-move-light.ps1` and Nightwing direct HID writes are + now smoke/bootstrap paths for hardware proof when Muninn is not yet running + on that host. - Odin's Muninn organ owns Move optical candidate extraction in `E:\Projects\Odin\crates\muninn-move-tracker` and publishes/feeds `muninn.move_marker_candidate.v1` records. Mimir consumes those candidate diff --git a/notes/current-system-map.md b/notes/current-system-map.md index 2a36503..9ffc0bf 100644 --- a/notes/current-system-map.md +++ b/notes/current-system-map.md @@ -110,6 +110,11 @@ Authority: - Starfire-local Move tracking is a local Mimir/Muninn tracking stream. - Nightwing Move tracking is emitted by Muninn on Nightwing over the typed observation path. +- Structured PS Move light pulses are Muninn output commands. Mimir requests + them by sending `muninn.move_light_command.v1` over CultNet/CultMesh to the + Muninn daemon on the host with the USB-attached Move; Mimir does not write + remote HID directly except through temporary smoke scripts used to prove + hardware behavior before Muninn is available on that host. - Odin discovers and projects the stream/schema surface for operator and agent access. - Mimir owns subscription, rolling retention, clock alignment, and later fusion @@ -123,18 +128,19 @@ Move observation into two tracking buffers. Live Nightwing bring-up uses `scripts/start-nightwing-move-tracking.ps1`. Starfire starts `Mimir.EveSensorReceiver` on `/eve/periwinkle`, stages `nw_eye_cap.py`, `nw_move_hint.py`, and `nightwing_typed_witness_publisher.py` -onto Nightwing, and launches the publisher with `--track-eyes` plus explicit -`--move-light name=/dev/hidrawN:#rrggbb` HID ownership. The worker keeps the -USB Move sphere lit with PS Move report `0x06`, emits -`mimir.psmove_light_state.v1`, and publishes compact +onto Nightwing, and launches the publisher with `--track-eyes` plus a heartbeat +freshness file. The publisher can still accept +`--move-light name=/dev/hidrawN:#rrggbb` as an explicit smoke/bootstrap edge, +but runtime structured light commands belong to Muninn. The worker publishes +compact `mimir.move_controller_observation_state.v1` blob observations from both PS3 Eyes. Those Eye/Move observations are the live optical witness feeding the later pose/fusion owner; they are not themselves the final 6DoF pose authority. -Starfire-local Move illumination uses `scripts/start-starfire-move-light.ps1`. +Starfire-local Move illumination smoke uses `scripts/start-starfire-move-light.ps1`. That launcher runs `Mimir.PsMoveProbe` against the local Windows HID col01 -output collection and refreshes the PS Move LED report so the USB-attached Move -stays visible as a tracking/calibration marker. +output collection and refreshes the PS Move LED report for hardware proof when +Muninn is not available on Starfire yet. Odin's Muninn organ owns the Move optical extraction stage for sensor stream exposure. Its Rust crate lives in `E:\Projects\Odin\crates\muninn-move-tracker` diff --git a/scripts/start-nightwing-move-tracking.ps1 b/scripts/start-nightwing-move-tracking.ps1 index f3397d5..1d8c9cd 100644 --- a/scripts/start-nightwing-move-tracking.ps1 +++ b/scripts/start-nightwing-move-tracking.ps1 @@ -4,9 +4,7 @@ param( [string]$StarfireHost = "192.168.1.66", [string]$Path = "/eve/periwinkle", [string]$EyeDevices = "/dev/video2,/dev/video3", - [string[]]$MoveLight = @( - "move-usb=/dev/hidraw1:#35ff6c" - ), + [string[]]$MoveLight = @(), [string]$RecorderRoot = "C:\Users\Meta\Videos\Mimir\VerseCaptures", [switch]$SkipRecorder, [switch]$DryRun @@ -18,6 +16,9 @@ $runId = Get-Date -Format "yyyyMMdd-HHmmss" $runDir = Join-Path $repo "artifacts\runtime\nightwing-move-tracking-$runId" $witnessUrl = "ws://$StarfireHost`:$Port$Path" $subscribeUrl = "ws://127.0.0.1:$Port$Path/subscribe" +$remoteLog = "~/.local/state/gamecult/mimir-nightwing-move-tracking-$runId.log" +$remotePid = "~/.local/state/gamecult/nightwing-typed-witness.pid" +$remoteHeartbeat = "~/.local/state/gamecult/nightwing-typed-witness.heartbeat" New-Item -ItemType Directory -Force -Path $runDir | Out-Null New-Item -ItemType Directory -Force -Path $RecorderRoot | Out-Null @@ -126,13 +127,11 @@ if ($DryRun) { scp (Join-Path $repo "tools\nw_move_hint.py") "${NightwingHost}:/tmp/nw_move_hint.py" | Out-Null scp (Join-Path $repo "tools\nightwing_typed_witness_publisher.py") "${NightwingHost}:/tmp/nightwing_typed_witness_publisher.py" | Out-Null - $remoteLog = "~/.local/state/gamecult/mimir-nightwing-move-tracking-$runId.log" - $remotePid = "~/.local/state/gamecult/mimir-nightwing-move-tracking-$runId.pid" $moveArgs = ($MoveLight | ForEach-Object { "--move-light '$($_ -replace "'", "'\''")'" }) -join " " $remoteScript = @" mkdir -p ~/.local/state/gamecult pkill -f '/tmp/nightwing_typed_witness_publisher.py.*--track-eyes' || true -nohup python3 /tmp/nightwing_typed_witness_publisher.py --url '$witnessUrl' --track-eyes --track-builtin-camera --track-builtin-mic --interval 0.10 --eye-devices '$EyeDevices' --eye-window-seconds 0.08 --tracking-stride 6 $moveArgs > $remoteLog 2>&1 < /dev/null & +nohup python3 /tmp/nightwing_typed_witness_publisher.py --url '$witnessUrl' --track-eyes --track-builtin-camera --track-builtin-mic --interval 0.10 --heartbeat-path '$remoteHeartbeat' --eye-devices '$EyeDevices' --eye-window-seconds 0.08 --tracking-stride 6 $moveArgs > $remoteLog 2>&1 < /dev/null & sleep 0.5 pgrep -n -f '/tmp/nightwing_typed_witness_publisher.py.*--track-eyes' > $remotePid cat $remotePid @@ -150,8 +149,9 @@ $manifest = [ordered]@{ runDir = $runDir witnessUrl = $witnessUrl subscribeUrl = $subscribeUrl + heartbeatPath = $remoteHeartbeat eyeDevices = $EyeDevices - moveLights = $MoveLight + directHidSmokeMoveLights = $MoveLight startedAt = (Get-Date).ToString("o") } $manifest | ConvertTo-Json -Depth 5 | Set-Content -Path (Join-Path $runDir "supervisor.json") diff --git a/state/evidence.jsonl b/state/evidence.jsonl index 3d0b9c1..9f5c7d5 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -128,3 +128,4 @@ {"ts": "2026-06-10T18:11:18+01:00", "type": "verification", "status": "ok", "note": "Started the Starfire-local USB Move light owner. Windows sees Sony VID_054C/PID_03D5 with col01 output reports; scripts/start-starfire-move-light.ps1 launched Mimir.PsMoveProbe PID 27344 with --rgb #35ff6c --hold-seconds 0 --refresh-ms 250, and artifacts/runtime/starfire-move-light-20260610-180943/move-light-events.jsonl shows repeated mimir.psmove_usb_pulse_event.v1 hold writes succeeding with ok rgb=#35FF6C bytes=49."} {"ts": "2026-06-10T20:33:54+01:00", "type": "implementation", "status": "ok", "note": "Added native/move_tracker as Rust-orchestrated PS Move optical candidate extraction: Rust owns dispatch/FFI/CPU mirror; HLSL owns 16px-tile luma reduction. Scope is marker candidates only, before calibration/triangulation/IMU fusion/prediction."} {"ts": "2026-06-10T20:49:06+01:00", "type": "decision", "status": "ok", "note": "Corrected Move optical candidate ownership: the Rust/HLSL tracker moved out of Mimir and into Odin's Muninn organ at E:\\Projects\\Odin\\crates\\muninn-move-tracker. Mimir consumes muninn.move_marker_candidate.v1 streams and no longer owns raw optical extraction."} +{"ts": "2026-06-11T07:57:05+01:00", "type": "decision", "status": "ok", "note": "PS Move structured light ownership moved to Odin/Muninn: Mimir requests muninn.move_light_command.v1 over CultNet/CultMesh; Muninn serve consumes host-addressed pending commands, writes local HID report 0x06, and updates command state. Nightwing direct HID launcher path is opt-in smoke/bootstrap only."} diff --git a/state/map.yaml b/state/map.yaml index 0ec7c31..639b97c 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -69,6 +69,10 @@ invariants: - Move tracking observations are stream samples, not program controls or dashboard truth. Starfire-local and Nightwing-remote Move samples must enter Mimir.Runtime as typed tracking buffers before Fensalir or Eve acts on them. + - Structured PS Move light pulses are Muninn output commands. Mimir requests + `muninn.move_light_command.v1` over CultNet/CultMesh from the Muninn daemon + on the host with the USB-attached Move; direct HID writes in Mimir scripts + are temporary smoke/bootstrap edges only. accepted_design: - `Mimir.slnx` owns the app surface. diff --git a/tools/nightwing_typed_witness_publisher.py b/tools/nightwing_typed_witness_publisher.py index 8b4648f..1fc8afa 100644 --- a/tools/nightwing_typed_witness_publisher.py +++ b/tools/nightwing_typed_witness_publisher.py @@ -447,6 +447,9 @@ def run(args: argparse.Namespace) -> None: if args.track_eyes: for payload in eye_tracking_observations(args, sequence): ws.send_binary(payload) + if args.heartbeat_path: + with open(args.heartbeat_path, "w", encoding="utf-8") as handle: + handle.write(f"{int(time.time())} {sequence}\n") sequence += 1 if args.once: return @@ -464,6 +467,7 @@ def main() -> int: parser.add_argument("--interval", type=float, default=0.25) parser.add_argument("--reconnect-seconds", type=float, default=2.0) parser.add_argument("--once", action="store_true") + parser.add_argument("--heartbeat-path", default="", help="Write a small freshness witness after successful sends.") parser.add_argument("--track-eyes", action="store_true", help="Publish compact Nightwing-local PS3 Eye Move-sphere observations.") parser.add_argument("--track-builtin-camera", action="store_true", help="Publish compact status for Nightwing-local non-Eye camera devices.") parser.add_argument("--track-builtin-mic", action="store_true", help="Publish compact ALSA microphone level observations.")