Merge the Idunn extraction: Odin no longer owns deployment authority

Idunn lived as a crate inside the repository of a service it manages, which
inverted the authority it exists to hold. It is now GameCult/Idunn with its
full 136-commit history; this merge removes the old body from Odin.

Cut: crates/idunn-daemon and vendor/cultmesh-rs. Odin keeps its own Idunn
projection (crates/odin-core/src/idunn.rs), its RUDP client, and its recipe
under deployment/idunn -- those are Odin's view of a managed relationship,
not Idunn's authority.

Conflicts resolved:
- crates/idunn-daemon/src/main.rs, scripts/linux/idunn-yggdrasil: deleted,
  per the extraction. Both live in GameCult/Idunn.
- docs/architecture.md: took the branch. Main still described Gjallar as
  Nightwing-resident under E:\Projects\Gjallar; it runs on Yggdrasil from
  /srv/gjallar/current, confirmed against the host.
- src/odin/documents.cjs: union. All three hunks were pure branch-side
  additions of the ghostlight.schema_catalog type; markers stripped rather
  than taking --theirs, to preserve auto-merged HEAD changes elsewhere in
  the file. node --check passes.

Verified: odin-core 22/22 on Windows; odin-daemon type-checks clean for
x86_64-unknown-linux-gnu, which is its real target -- it is unconditionally
Unix (systemd socket activation via File::from_raw_fd) and does not build
on Windows by design.

main is tagged pre-idunn-extraction-main: the last tree containing the
swarm keepalive supervision and the July Bifrost Persona feedback target,
neither of which exists on the branch or in GameCult/Idunn. See the merge
notes for why that matters.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-09-05 22:33:39 +02:00
commit 1cb0a2f68f
7 changed files with 712 additions and 268 deletions

View file

@ -15,8 +15,8 @@ path = "src/main.rs"
[dependencies]
anyhow = "1"
cultmesh-rs = { path = "../../vendor/cultmesh-rs" }
cultnet-rs = { path = "../../vendor/cultnet-rs" }
cultmesh-rs = { git = "https://github.com/GameCult/CultLib.git", rev = "c13b6ba07e99f2535b455da74d07d88c308731f5", package = "cultmesh-rs" }
cultnet-rs = { git = "https://github.com/GameCult/CultLib.git", rev = "c13b6ba07e99f2535b455da74d07d88c308731f5", package = "cultnet-rs" }
libc = "0.2"
muninn-move-tracker = { path = "../muninn-move-tracker" }
muninn-psmoveapi-tracker = { path = "../muninn-psmoveapi-tracker", optional = true }

File diff suppressed because it is too large Load diff

View file

@ -166,19 +166,29 @@ mod linux {
}
let serial = unsafe { text(psmove_get_serial(handle)) };
let move_id = format!("move-{}", serial.replace(':', "").to_ascii_lowercase());
if self.controllers.iter().any(|controller| controller.move_id == move_id) {
if self
.controllers
.iter()
.any(|controller| controller.move_id == move_id)
{
unsafe { psmove_disconnect(handle) };
continue;
}
let Some((_, color)) = self.colors.iter().find(|(identity, _)| {
identity.eq_ignore_ascii_case(&move_id)
}) else {
let Some((_, color)) = self
.colors
.iter()
.find(|(identity, _)| identity.eq_ignore_ascii_case(&move_id))
else {
unsafe { psmove_disconnect(handle) };
continue;
};
let status = unsafe {
psmove_tracker_enable_color_observer(
self.tracker, handle, color[0], color[1], color[2]
self.tracker,
handle,
color[0],
color[1],
color[2],
)
};
if status == TRACKER_CALIBRATED {
@ -192,9 +202,11 @@ mod linux {
}
pub fn set_expected_color(&mut self, move_id: &str, color: [u8; 3]) -> bool {
let Some(controller) = self.controllers.iter().find(|controller| {
controller.move_id.eq_ignore_ascii_case(move_id)
}) else {
let Some(controller) = self
.controllers
.iter()
.find(|controller| controller.move_id.eq_ignore_ascii_case(move_id))
else {
return false;
};
unsafe {
@ -275,7 +287,9 @@ mod linux {
if value.is_null() {
return String::new();
}
unsafe { CStr::from_ptr(value) }.to_string_lossy().into_owned()
unsafe { CStr::from_ptr(value) }
.to_string_lossy()
.into_owned()
}
}
@ -301,20 +315,29 @@ impl PsmoveApiTracker {
unreachable!()
}
pub fn calibrate_connected(&mut self) -> usize { 0 }
pub fn calibrate_connected(&mut self) -> usize {
0
}
pub fn observe_connected(&mut self) -> usize { 0 }
pub fn observe_connected(&mut self) -> usize {
0
}
pub fn set_expected_color(&mut self, _move_id: &str, _color: [u8; 3]) -> bool { false }
pub fn set_expected_color(&mut self, _move_id: &str, _color: [u8; 3]) -> bool {
false
}
pub fn tracked_controller_count(&self) -> usize { 0 }
pub fn tracked_controller_count(&self) -> usize {
0
}
pub fn update(&mut self) -> Vec<PsmoveApiObservation> {
Vec::new()
}
pub fn rgb_image(&self) -> Option<(u32, u32, Vec<u8>)> { None }
pub fn rgb_image(&self) -> Option<(u32, u32, Vec<u8>)> {
None
}
}
#[cfg(test)]

View file

@ -1,2 +1,2 @@
@echo off
powershell.exe -NoProfile -ExecutionPolicy Bypass -File E:\Projects\Odin\scripts\activate-muninn-raven-av-srt.ps1
powershell.exe -NoProfile -ExecutionPolicy Bypass -File %~dp0activate-muninn-raven-av-srt.ps1

View file

@ -7,4 +7,4 @@ if /I not "%IDUNN_COMMAND_AUTHORITY%"=="idunn-daemon" (
echo restart-muninn.cmd is an Idunn actuator wrapper. Redeploy by poking Idunn; direct service restart is not an owned path. 1>&2
exit /b 1
)
powershell.exe -NoProfile -ExecutionPolicy Bypass -File E:\Projects\Odin\scripts\restart-muninn.ps1
powershell.exe -NoProfile -ExecutionPolicy Bypass -File %~dp0restart-muninn.ps1

View file

@ -7,4 +7,4 @@ if /I not "%IDUNN_COMMAND_AUTHORITY%"=="idunn-daemon" (
echo restart-nightwing-muninn.cmd is an Idunn actuator wrapper. Redeploy by poking Idunn; direct service restart is not an owned path. 1>&2
exit /b 1
)
powershell.exe -NoProfile -ExecutionPolicy Bypass -File E:\Projects\Odin\scripts\restart-nightwing-muninn.ps1 -DiscoverMoveState -ClaimUsbMoves
powershell.exe -NoProfile -ExecutionPolicy Bypass -File %~dp0restart-nightwing-muninn.ps1 -DiscoverMoveState -ClaimUsbMoves

View file

@ -7,4 +7,4 @@ if /I not "%IDUNN_COMMAND_AUTHORITY%"=="idunn-daemon" (
echo restart-starfire-muninn.cmd is an Idunn actuator wrapper. Redeploy by poking Idunn; direct service restart is not an owned path. 1>&2
exit /b 1
)
powershell.exe -NoProfile -ExecutionPolicy Bypass -File E:\Projects\Odin\scripts\restart-starfire-muninn.ps1
powershell.exe -NoProfile -ExecutionPolicy Bypass -File %~dp0restart-starfire-muninn.ps1