The drift was 94 hunks across 4 files, not 94 files as I described it earlier.
muninn-daemon carries almost all of it; sleipnir-daemon needed four lines.
Checked rather than assumed. Ignoring whitespace, the only remaining deltas are
trailing commas rustfmt adds when it wraps an argument list, and braces removed
from single-expression closure bodies. Both are semantics-preserving.
sleipnir-daemon's change is whitespace and nothing else.
Everything except the Unix-only odin-daemon builds; muninn and sleipnir pass 162
tests, with the same pre-existing media-channel failure.
vendor/cultmesh-rs is its own workspace so `cargo fmt` does not reach it, but it
reports no drift of its own.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This had been sitting uncommitted in the worktree. It is real work rather than
stray edits: RouteBinding gains stable_socket and an NginxStreamUdp driver so a
route can be actuated over UDP, control_plane and drivers grow the Idunn-owned
projection and bounded RUDP transport, and crates/odin-daemon arrives as a new
member of the workspace.
The deployment recipe comes with it, including the required_gitlinks fix the
core-stack repoint made necessary: it named vendor/cultnet-rs, which no longer
exists now that CultNet comes from CultLib, so Idunn would have refused to admit
the target. The list is empty because Odin has no submodules left; the core
stack is pinned by revision in Cargo.lock inside the frozen source tree.
Everything except odin-daemon builds here. odin-daemon reads systemd listen
file descriptors through std::os::fd and cannot compile on Windows by design, so
Linux CI is its first real witness. muninn and sleipnir pass 162 tests; the one
failure expects an Unreliable media channel that no CultNet lineage has ever
declared, and predates this.
Committed rather than left in flight. rustfmt reports 94 files across the repo,
which predates this work, so formatting is left for its own pass instead of
being buried in a 4,000-line diff.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The CultNet submodule and the in-tree CultCache copy are gone. Both now come
from CultLib, and vendor/cultmesh-rs is the only fork left -- it too consumes
CultLib, so exactly one version of each crate spans the graph. That mattered:
mixing sources would have put two cultnet-rs crates in one build, and the types
would not have unified.
The in-flight CultMesh RUDP document server comes with it because it is a
prerequisite, not a coincidence. The previously committed CultMesh calls
assume_connected(), a CultNet method Odin's fork carried and CultLib does not,
so the old code cannot build against CultLib at all. The newer code no longer
calls it. Verified by reverting the file and watching it fail.
Three API differences needed adapting: CultLib's transport options carry a
reconnect_policy the fork lacked (7 sites), its create_ack builds the packet
straight from ack state and so cannot fail, and its transport profile owns each
channel's reliable expiry.
Everything but odin-daemon builds; odin-daemon is Unix-only and does not compile
on this machine either way. muninn and sleipnir pass 162 tests. The one failure,
rudp_media_transport_options_follow_low_latency_profile, expects an Unreliable
media channel while every CultNet lineage including both revisions Odin had
pinned declares it Reliable, so it failed before this change too.
The in-flight idunn-daemon work is deliberately left uncommitted; the committed
tree was verified to build without it. Also left alone: the untracked
odin-daemon crate and deployment recipe, and the root manifest, whose now-dead
vendor excludes are inert. That recipe still requires the vendor/cultnet-rs
gitlink and will refuse admission until that line is dropped -- the fix is in
the working tree, waiting on that directory being tracked.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The previous commit fixed the target catalog and the operator alarm, but the
actuators the catalog invokes carried the same E: paths. Idunn would have
resolved every target and then failed on the first restart or deploy it ran,
for exactly the reason the alarm failed.
Rebased 41 references across 27 scripts:
- .cmd bodies invoke their sibling .ps1 through %~dp0 instead of an absolute
drive path, and restart-weksa.cmd reaches its sibling repo the same way.
- .ps1 parameter defaults and assignments derive from $PSScriptRoot: one level
up for paths inside Odin, two for sibling repos under the projects root.
Left deliberately alone: $RemoteViliRoot and $StateRoot in restart-vili.ps1.
Both are consumed inside the EncodedCommand block that restart-vili ssh's to
raven, so they describe raven's filesystem, not starfire's. Whether raven also
moved off E: is an operator question, not something to infer from here.
Verified: all 46 scripts under scripts/ parse clean, and the derivation
resolves to F:\Projects\Odin and F:\Projects on this host.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The projects root moved from E: to F:, but Idunn's starfire-local surfaces
still named E:\Projects. Local Idunn died on 2026-08-16 with "fatal: cannot
change to 'E:\Projects\Heimdall'" and every one of its 16 operator alarms
also failed (0xfffd0000), because notify-idunn-operator-alarm.cmd shelled to
an E: path that no longer existed. The supervisor was down for 18 days and
could not say so.
Rather than swap one hardcoded drive letter for another, derive the projects
root the way this catalog already derives its repo root:
- notify-idunn-operator-alarm.cmd invokes its sibling via %~dp0.
- notify-idunn-operator-alarm.ps1 resolves Bifrost from the projects root.
- idunn-deployment-targets.ps1 gains $projectsRoot and rebases 19 LocalPath
values onto it. The remote /srv/build/VoidBot path is left alone.
Verified: the catalog resolves 15 of 20 targets to real directories, the
remote target is untouched, and the alarm chain now runs to exit 0 emitting
a valid gamecult.operator_dm_request.v1 under IDUNN_OPERATOR_ALARM_DRY_RUN.
Still broken, not addressed here: stonks, vili, StreamPixels and repixelizer
have no directory under F:\Projects, and the Bifrost publisher's non-dry path
throws "definition.schema.parse is not a function" against the current
CultMesh.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>