Route Move light ownership through Muninn

This commit is contained in:
Meta Vens 2026-06-11 07:58:26 +01:00
commit 4d661967ae
6 changed files with 38 additions and 20 deletions

View file

@ -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

View file

@ -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`

View file

@ -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")

View file

@ -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."}

View file

@ -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.

View file

@ -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.")