Commit graph

611 commits

Author SHA1 Message Date
Meta Vens
f4a1f8900a Odin: drop doc lines that restate the code they sit on
One was also wrong: `records` is in key order, not the file's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:32:41 +02:00
Meta Vens
c94b5c4f85 Odin tests: the real binary; an acknowledged put survives SIGKILL, SIGTERM stops it cleanly
From Soul's SIGTERM probe (scratch 5c379dd), made a test. It runs the built
odin-daemon under an Idunn-shaped world with the warming probe and lease
grant made over RUDP. With puts written before they are acknowledged, the
SIGKILL round is the rule's test; the SIGTERM case pins `main`'s signal
wiring, which no in-process test reaches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:30:32 +02:00
Meta Vens
0a09df9b7c Odin: a peer's put is written before it is acknowledged (Q3 B)
Operator ruling Q3 B: `accept_raw_document` returns Ok, and so the server
acknowledges the put, only once the store holding it is on disk. The write
is the one `flush`, under the same lease check, so it also carries every
other unwritten change. A write that is not made refuses the put. Odin's own
bookkeeping stays on the one-second interval.

The interval tests now change Odin's own bookkeeping (its heartbeat) instead
of putting, since a put is no longer an interval change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:30:28 +02:00
Meta Vens
3afa3fb778 Odin: every way out of the serving loop makes the last write
The loop is `serve`, and it ends in one place: a stop request, a condition
`survive` returns, or a dead socket all reach `stop`, whose write is made
only while the lease is current and the file is still Odin's. Tested for
each exit kind: a stop request, a refused own authority and a dead socket
write what changed; a lost lease and a foreign write write nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:27:53 +02:00
Meta Vens
a4aa5fcf97 Odin: a failed write is retried as it stands, and its own replaced file is not a foreign write
The records stay dirty until a write lands, so the next write makes the
failed change without another mutation (tested with no heartbeat to
re-dirty them). A write that fails after it replaced the file (the
directory sync) leaves Odin's own records there; they are remembered as
the write's attempt and accepted as a second baseline until a write lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:26:25 +02:00
Meta Vens
620efb85d8 Odin: a catalog query reads Idunn's projection once
The file-backed projection source no longer answers lookups itself, so no
caller can read the file once per lookup: every lookup is made against one
snapshot. The catalog query takes one per query, as the refresh pass does;
startup, activation and the own-projection check take one each.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:24:32 +02:00
Meta Vens
2ad60183a1 Odin: the self presence counts from its own launch; the stored-sequence continuation is gone
Every launch is issued a fresh activation (Idunn control_plane.rs, the
continuity demotion), presences are ordered only within one activation
(select_presence), and Idunn compares only the warming presence's digest.
Continuing from a stored sequence protected nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:14:25 +02:00
soul-probe
cda20870fd Odin tests: the write starts the next interval; unprojected correlations are withdrawn
cargo-mutants survivors, both real gaps:
- serving_pass with the timer condition inverted wrote every change on the
  next pass after a write; the interval test set the timer by hand on every
  pass and never saw the loop set it. A change right after a write now waits.
- correlated_incarnations returning nothing left a correlation whose
  incarnation Idunn stopped projecting in place forever; the lib test
  refreshed that incarnation by name. The refresh pass now has to find it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:07:44 +02:00
soul-probe
35ea0d45fc Odin test: with nothing to write, the write step reads nothing, not even the lease
The flush step is due on every pass until something changes. Hand mutant M5b
(the daemon skipping its own dirty check) left every write rule intact but read
the lease file on every 2 ms pass; no test saw it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:39:47 +02:00
soul-probe
8189623411 Odin: the correlation record type is imported only where it is used
Cut 1 left it imported at the top of main.rs, where only the tests use it;
the release build warned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:32:11 +02:00
soul-probe
b5f13308e9 Odin Cut 2: one write of the store file per interval, only when it changed
Every admission, put and refresh that changed something rewrote and fsynced
the whole store; a heartbeat did it twice (watermark, then correlation).
Now the serving loop writes the file at most once per FLUSH_INTERVAL (1 s,
operator default Q3), and only when the working set changed.

Deleted first: the per-mutation writes Cut 1 left in accept_raw_document,
publish_self_presence and refresh_all_correlations. The watermark's own write
went with the file store in Cut 1; its mark now travels in the same atomic
write as the correlations that use it. "Published" means written.

Added: FLUSH_INTERVAL, the flush step in serving_pass, and a final write on
SIGTERM/SIGINT. The dirty flag lives in MemoryOdinTopologyStore. RuntimeState::
flush is the only write of the file: it checks the lease immediately before
writing, and CultLib's snapshot compare-exchange against what Odin last loaded
or wrote refuses a file another process wrote (ForeignStoreWrite). survive
treats ForeignStoreWrite like WriteLeaseLost: both end Odin. An attempt, failed
or not, starts the interval; an interval with nothing to write does not.

Tests: 50 changes inside one interval are one write, not made at 0.9 s and
made at 1.1 s after the last; nothing changed is no write; a lease lost before
the write writes nothing and ends Odin; a foreign write ends Odin and is not
written over; stopping writes only under the lease; a crash and reload never
republishes a written sequence, withdrawal included; a flush writes only
changes and never over a foreign file. The failed-publication test becomes a
failed-write test: the store is no longer read by publication.

Map: docs/write-pattern-cut.md, Cut 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:00:53 +02:00
soul-probe
409d92f279 Odin Cut 1: the store file stops being working memory
Odin read and decoded its whole 3.24 MB store file about 30 times a second:
every refresh pass, every admission, every catalog query and every CAS retry
read it again. The working set now lives in memory under the write lease.

Deleted: CultCacheOdinTopologyStore (every file read and CAS against the
store, and its four CAS_ATTEMPTS retry loops, including the one in
reconcile), persist_generic_document's file CAS loop, the store half of
incarnation_keys, stored_snapshot's file read, and
prior_self_publisher_sequence's file read in RuntimeState::open. With one
writer under the lease an in-memory exchange cannot lose, so nothing retries.

Added: MemoryOdinTopologyStore, keyed (type, key), implementing the
OdinTopologyStore trait (still the mock point). It is loaded once, with the
locked pull_all, in try_activate after the lease is verified; legacy
retirement and the self publisher sequence are operations on the loaded set.
The trait's compare_exchange collapses into commit. Refresh reads Idunn's
projection once per pass (IdunnProjectionSnapshot) instead of once per
incarnation; admission reads it once per admission.

Not in this cut: the write policy. Each mutating operation still writes the
whole file immediately, now from memory (flush after an admission, a put or a
refresh pass that changed something).

Tests: the two tests that corrupted the store while Odin served now put the
bad record in the file at activation. New: rewriting the file behind Odin
changes nothing it serves; refresh passes and catalog reads succeed with the
file replaced by bytes that do not decode; a loaded store never reads its
file again.

Map: docs/write-pattern-cut.md, Cut 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:58:52 +02:00
soul-probe
4b525b463c Map Odin's write pattern: memory working set, one write per interval
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:39:32 +02:00
soul-probe
44951a1f07 Merge Odin fixes 2-4: one bad record never stops Odin, peers write only what they own
A record that does not decode is skipped per record (catalog, startup).
Every failure of Odin's own authority ends it (temporary, until Idunn
cut A3); an early clock and a real file-read error are retried. The
catalog no longer serves correlations or the watermark. Peer puts are an
evidence-based allow-list, closing a peer-reachable presence freeze.
Three Soul passes; deploy gate GO against the live type inventory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 06:17:18 +02:00
soul-probe
dc46be205a Odin: the projection-unreadable mark is found through anyhow context layers
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 05:23:54 +02:00
soul-probe
5dd5b4a863 Odin: peer namespaces are the ones a source publishes, and only a failed file read is retried
The allow-list drops nine guessed namespaces and gains gamecult.model,
gamecult.aetheria and the two gamecult.media_stream_* types (they are not
under a dotted gamecult.media segment, so they are whole types), each with its
publisher named. The own-projection failure rule now retries only what the
file read itself marked, so a truncated Expected record ends Odin.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 05:19:46 +02:00
soul-probe
c0735f17aa Odin: providers write only their own namespaces, own-projection I/O errors are retried, the lingering test no longer races the idle timeout
Peer writes (Soul P-B, confirmed): persist_generic_document blocked six
authority types, so a peer could put an odin.topology_publisher_watermark keyed
odin holding the largest sequence; every heartbeat then failed to reserve its
sequence, and the record survived restarts. Generic puts are now an allow-list
of provider namespaces (PEER_DOCUMENT_NAMESPACES). Odin's own records and
Idunn's projected authority live in namespaces no provider can name, so they
are refused by construction. The same predicate decides what the catalog
serves back, replacing the correlation special case: the watermark, and any
future Odin-internal type, is no longer public.

Own projection: a plain I/O error reading Odin's own projection (permission
denied, not found, interrupted) or a missing file is survived and retried; an
error the reader decoded or validated and did not accept stays fatal
(PresenceAuthorityRefused).

Log flood: survive() now logs through the RuntimeState LogGate, once per
subject per minute, instead of printing every pass.

Flake: self_presence_lands_while_lingering_publishers_hold_every_session failed
on Yggdrasil because 64 peers connect over about 9 s and the fsync-bound passes
that follow took 4 to 20 s under disk pressure, so the earliest sessions passed
the server's default 30 s idle timeout and expired before the final
session_count assertion (44 of 64, measured). No peer ever failed to connect.
The test's world now serves with a one hour idle timeout, since the property is
a full table at heartbeat time, and it logs any peer that is not admitted.

Tests: provider puts of every Odin-owned kind are refused and presence keeps
advancing; the catalog serves only presence and provider documents; namespaces
match whole segments; I/O versus decode of the own projection, and a missing
projection file through the serving loop; repeated failures are counted, not
printed again.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 03:57:40 +02:00
soul-probe
64e64df3bd Odin test: a refresh before the anchor's binding still records the time disagreement
Removing the incoming-claim condition from the clock exemption in reconcile
survived: only the admission side was pinned. A refresh has no claim to refuse,
so with the clock before the anchor's binding it must still write the
correlation carrying the provider-trust-anchor-time disagreement.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 03:57:39 +02:00
soul-probe
2f0d1d4bcb Odin test: the lingering-publisher test admits until 64 are held, then refuses one
A peer that times out on a loaded host no longer changes the count, and the six refused peers no longer wait out their deadline while the first sessions idle out.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 02:14:27 +02:00
soul-probe
c81fc38ecc Odin tests: the catalog test expects the watermark record, the lingering test counts from a first pass
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 02:07:22 +02:00
soul-probe
8c33a18729 Odin: repair a mis-spliced edit in the sink handle (the previous commit did not compile)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 02:04:00 +02:00
soul-probe
2e4ccc40ad Odin: a bad record is skipped, own-authority failures are fatal, correlations leave the catalog
A1 the catalog and startup skip a record that does not decode (logged); startup
reads only presences keyed under Odin's own target.
A2 every failure to establish Odin's own projected authority is
PresenceAuthorityRefused (temporary rule in survive).
A3 a clock that precedes the provider anchor's binding is retried, not refused.
C  the catalog no longer serves correlations; the store still writes them.
B  test peers connect while the server is polled without timers; 2 s deadline.
6  repeating refresh and catalog-skip lines are logged once per minute per subject.
Soul's probes P1-P3 become assertion tests.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 02:01:48 +02:00
soul-probe
59667f4648 Odin tests: Soul's probes P1-P3 for catalog collision, one bad record, and undecodable own anchor
P1 two incarnations of one target, P2 one undecodable presence, P3 an
undecodable own provider anchor. All three fail at c34d167; the fixes follow.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 01:54:48 +02:00
soul-probe
c34d167f74 Merge Odin session-table fix: Odin survives a full session table
Odin admits its own presence straight into its store instead of over
RUDP, survives transient failures, and ends only on write-lease loss or
a refused own authority (temporary, until Idunn cut A3). Merged to stop
a live crash loop on Yggdrasil (2026-09-30 00:55 CEST): the deployed
Odin timed out publishing to itself through a full session table and
Idunn stopped restarting it after three failures. Open Soul findings
(A1 startup decode, A2 rule gaps, C catalog collision, flaky harness
test) are pre-existing in the deployed build and are fixed next.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:21:12 +02:00
soul-probe
68b666c2e5 Merge X1: delete Odin's dead lifecycle residue (-7,037 lines)
odin-core idunn.rs and idunn.*/bifrost schemas, the retired JS
coordinator, dead deploy/restart/health scripts, lifecycle claims in
docs. Soul: nothing deleted is reached by the deployed odin-daemon, the
Hermodr container or any live store. Idunn map cut X1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:48:07 +02:00
soul-probe
cc7e7f9015 Odin: drop the second projection-validity marker; the source that assembles a projection owns it
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 00:33:12 +02:00
soul-probe
8d241efb72 Odin test: a catalog read does not refresh the projection
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 00:27:14 +02:00
soul-probe
106dfb8327 Docs: Idunn owns deployment and daemon survival; Odin does discovery only
README and architecture.md called Idunn "Odin's keepalive organ", listed
crates/idunn-daemon (not in this repo) and the deleted odin-core idunn.rs
as its body, described the Node coordinator's process lifecycle, refresh
loop and Docker/ADB probes as Odin's runtime body, and pointed at the
deleted start-odin.ps1. Rewritten to the live truth: Idunn builds, activates,
restarts and brakes every target, Odin included; odin-daemon reads Idunn's
projection, admits presences, publishes correlation records and answers RUDP
requests; process lifecycle is not Odin's.

The dated ledger (transport-shortcut-inventory.md), notes/ and the Hermodr
extraction plan are history and are left as written.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 00:25:20 +02:00
soul-probe
779c24ba80 package.json: drop scripts that named the deleted coordinator and a missing crate
start (node src/odin-coordinator.cjs), check and test (JS gates over the
deleted src/ and test/), muninn:build and muninn:start (muninn-daemon is
not in this workspace). gjallar:persona and rust:test stay. This belonged
in the Node coordinator deletion commit and was left unstaged there.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 00:23:07 +02:00
soul-probe
99f9a22fa4 odin-core: keep the cultnet-rs dependency (cultmesh_documents! expands to it)
The previous commit dropped cultnet-rs from odin-core's manifest as
unused; cultmesh_documents! emits cultnet_rs paths, so the crate needs it
in scope. Restore the dependency and its lockfile entry.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 00:22:45 +02:00
soul-probe
092ff997b4 Delete deploy, restart, health and start/stop scripts for other services
Odin does not deploy, restart or health-probe anything: Idunn owns
deployment and daemon survival, and every service in this set is either
Idunn-deployed from its own repo recipe or archived. Removed from
scripts/: deploy-yggdrasil-{heimdall,repixelizer,source-app,streampixels}
(.ps1/.cmd, armed behind IDUNN_ACTUATOR=1) and the linux heimdall deploy;
restart-* (odin, stonks, vili, weksa, nightwing eve dashboard and browser
reference; several already exit 2 or throw as archived); health-* (odin,
voidbot, stonks, vili, weksa, mimir, nightwing, raven capture mux,
yggdrasil heimdall/repixelizer/streampixels/source-app; archived stubs and
orphans); start-odin.ps1 and stop-odin.ps1 (launched the deleted Node
coordinator).

Kept: write-gjallar-persona-cc.mjs (persona tooling, package.json
gjallar scripts) and the nightwing usb-move helpers, wasapi loopback,
firewall and wireguard scripts, none of which is a lifecycle actuator.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 00:22:19 +02:00
soul-probe
06282c47d8 Delete the retired Node coordinator, its tests and npm entry points
src/odin-coordinator.cjs and src/odin/* (probes.cjs docker/adb host
probes, state.cjs, provider-ingress.cjs with its 120 s TTL) were retired
when the Rust odin-daemon became the deployed body (state/map.yaml: the
Node coordinator that held 17871 is retired). The recipe builds only
odin-daemon; nothing in the Rust crate graph loads a .cjs file. The live
Yggdrasil hermodr container runs from the immutable release
/srv/odin/current, not from this tree.

Removes src/, test/ (4 test files for that JS), scripts/check-syntax.cjs
(the JS syntax gate), and the package.json scripts start, check, test,
muninn:build, muninn:start (the last two named a crate that is not in the
workspace). gjallar:persona and rust:test stay.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 00:21:30 +02:00
soul-probe
6aba9a8801 Delete odin-core's Idunn lifecycle planner and idunn.* schemas
crates/odin-core/src/idunn.rs (plan_keepalive: observe, alarm, deploy or
restart from IdunnDaemonHealthRecord) had no caller: odin-daemon does not
depend on odin-core, and the deployed recipe builds only odin-daemon.
Idunn owns deployment and daemon survival; nothing in Idunn reads these
records (its own live in cultnet-rs).

Also removes from documents.rs the idunn.* and bifrost release-authority
schema constants and records, their OdinDocuments registrations, the
cultnet re-exports of Idunn health types, and the tests that only
exercised them. The muninn.* copies stay. cultnet-rs and rmp-serde drop
out of odin-core's manifest and lockfile entry (no remaining user).

Muninn pins odin-core at 3e96c6c and is unaffected until its next bump,
which must drop IdunnDaemonHealthRecord.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 00:20:38 +02:00
soul-probe
b6cbf53a54 Odin: an invalid projection of Odin's own incarnation is a refused authority; sibling test uses another target
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 00:17:16 +02:00
soul-probe
24f163cf14 Odin: one bad incarnation no longer stops the catalog; unreadable lease is a lost lease; refused self-presence authority ends Odin
Refresh reads only incarnation keys and refreshes each incarnation on its own;
a record that will not decode is that incarnation's logged failure. The
CultCache projection source decodes only the requested incarnation's records.
Catalog reads serve the stored projection instead of refreshing everything.
An unreadable process-write lease maps to WriteLeaseLost. Temporary named
rule: a self-presence Odin's authority refuses (PresenceAuthorityRefused) is
fatal in survive until Idunn proves Odin by its own route challenge.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 00:12:07 +02:00
Meta Vens
eeb68124ca Cargo.lock is the CultLib pin; delete deploy/cultlib.commit and dead muninn scripts
deploy/cultlib.commit said 542ddd3 while the built pin is Cargo.lock's 3bf1c0c.
Nothing reads the file (the Idunn recipe builds with `cargo --locked`), so it is
deleted and the README names the lock. package.json's muninn:build/muninn:start
named a muninn-daemon crate that no longer exists in this workspace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:28:20 +02:00
Meta Vens
a9ed585263 Odin's liveness is Odin's: self-presence goes straight into its own store
Odin published its own heartbeat over RUDP to its own document server, which
holds 64 sessions for 30 s after each peer's last packet. Ghostlight,
CodexConnector and the presence publishers never send Disconnect, so a burst of
publishes filled the table, Odin's Connect was dropped, the heartbeat failed and
`main` returned. Reproduced with 70 lingering sessions: 4 of 5 self-publishes
failed.

Owner change: Odin is the store, so its heartbeat is signed and admitted through
the same admission path providers use (`admit_presence_document`), with no
socket, no thread and no session slot. The self-publish timeout and the RUDP
publisher are deleted.

Serving-loop failure policy, in one place (`survive`, `settle_poll`): only
`WriteLeaseLost` (the process-write lease withdrawn or replaced, i.e. serving on
would be a second writer) ends Odin. A failed heartbeat, a failed projection
refresh and a failed poll are logged and retried; a socket failing every poll for
30 s is a dead socket and ends Odin so Idunn restarts it. An application
rejection or stray packet never ends Odin. The startup publish/refresh pair is
folded into the loop (a timer that has not fired is due). One serving pass is
`serving_pass`, the unit the tests drive against Odin's real activated state and
production RUDP server.

Tests (Linux, real activation, lease, projection and identities): a full 64-wide
session table of lingering publishers does not stop 5 consecutive heartbeats
landing in the store; a corrupted store fails publication and refresh without
ending Odin and the next pass lands; replacing or removing the lease ends Odin;
an application rejection ends only the offending session and a stray datagram is
dropped while Odin keeps admitting peers; a failing socket is retried until the
failure limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:28:19 +02:00
Meta Vens
6eb0bd82e5 Presence ordering: pin the two ways a stored presence is not the same publisher
A stored presence that names the current activation but no longer authenticates
at its own received time is an error (fail-closed): its count is unknowable, so
the claim must not slip past it. A stored presence that cannot be decoded names
no activation, so it is another publisher's and the claim supersedes it
(fail-open). The choice is now written on the branch and each half has a test
that fails when it flips.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:28:18 +02:00
Meta Vens
5c378609bc Presence ordering: same publisher is an activation identity, not an auth outcome
The stored presence constrains an incoming claim's sequence only when it names
the current activation (activation_witness_sha256 equals the authority's
activation_sha256). Previously any re-authentication failure meant "different
publisher", so a same-activation presence that stopped authenticating silently
lost its sequence. Now such a failure is an error.

Adds a test pinning that the stored presence is re-authenticated at its own
received-at time: sequence 5 admitted at T, sequence 4 offered at T+40s from
the same activation must be refused as reordered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:12:18 +02:00
Meta Vens
2dea7f6eed Bump CultLib pin to 3bf1c0ce (RUDP stray-packet hardening)
Odin crashed on a stray RUDP packet; CultLib 3bf1c0ce hardens stray-packet
handling in all runtimes. Both manifests (odin-core, odin-daemon; Odin has no
workspace.dependencies) move from a8aeddac to 3bf1c0ce. No API breaks: the
workspace compiles and tests unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:11:27 +02:00
Meta Vens
d2e9234d79 Delete crates/sleipnir-daemon: Sleipnir lives in the Muninn workspace
Sleipnir moved into Muninn with its history (Muninn f4f1f85, operator ruling
Q9); the StreamPixels ship that gated this deletion completed 2026-09-29.
Removes the crate, its workspace member, its Cargo.lock entries (including
vigem-client), the sleipnir:build/sleipnir:start package scripts, and the
deploy/restart/start launcher scripts that shipped Odin's sleipnir.exe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:09:41 +02:00
Meta Vens
db041ecb4e Clone the stored presence payload the new tests read back
unique_envelope returns a borrow; the helper moved out of it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:27:51 +02:00
Meta Vens
dbee042a47 Order presence publisher sequences within one activation only
From 2026-09-29 19:20 on yggdrasil every new StreamPixels incarnation's
runtime presence was refused with "runtime presence publisher sequence
was reordered". Odin compared the incoming claim's sequence with the
target's stored presence whoever had published it; the provider counts
from 1 in each process, so once a target had published for a while no
restarted activation could ever be admitted.

A publisher is the activation whose key signs its claims. The stored
presence now constrains the incoming claim only when it still
authenticates under the same current authority. One left by an earlier
activation, or otherwise stale, is superseded whatever its sequence.
Within one activation a lower sequence is still a reorder and an equal
one with different bytes is still a reuse, and a claim that does not
authenticate under the current activation is still refused.

The unconditional decode of the stored presence at the top of
select_presence existed only to feed that comparison and is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:26:27 +02:00
Meta Vens
379b826954 Align Odin CultLib with StreamPixels RUDP 2026-09-28 12:59:45 +02:00
Meta Vens
385df0f230 Merge the StreamPixels CultLib archive list (StreamPixels Cut E)
The StreamPixels deploy archive now carries CultLib's root build files,
contracts/cultnet, cultmesh-ts and cultmesh-browser, so the host can
build CultLib's TS dist/ itself. It previously relied on a June tarball
that happened to include dist/. This was verified on a clean Debian 13
extract and gated by Soul with StreamPixels Cuts E and F.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 14:25:43 +02:00
Meta Vens
96a55ec870 Let an external-operator-binding dependency not block Ready
Odin has no incarnation to observe for a provider Idunn admitted from an
operator binding, so it can never sign evidence for one, and every such
dependency stayed ready: false. A dependent with one (Ghostlight Dungeon's
Heimdall command boundary) could never become Ready, and Idunn waited in
AwaitingReady indefinitely. Idunn and CultLib already accept the kind.

The dependency's own evidence stays ready: false; only its dependent's
Ready no longer waits on it, as with optional. The dependent checks that
provider itself at use. The rule is now one named function with a test
covering managed, optional and external kinds; dropping the external kind
fails it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 19:29:24 +02:00
Meta Vens
4ac621ce8e Carry contracts/cultnet in the StreamPixels CultLib archive
cultnet-ts's build (generate-swarm-contracts.mjs) mirrors CultLib's
canonical contracts/cultnet into its own package tree at build time, so
`npm run build:ts` fails on cultnet-ts on a host that only has the
packages the previous archive list carried. Verified by a dry run of the
Cut E archive on Yggdrasil: build:ts failed with ENOENT on
CultLib/contracts/cultnet until this path was added.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 15:58:50 +02:00
Meta Vens
1449640ef0 Carry CultLib's build files and cultmesh-ts/cultmesh-browser in the StreamPixels archive
The archive built only packages/cultnet-ts and packages/cultcache-ts, and
dist/ is gitignored in both, so the current actuator ships CultLib
packages with no dist/ and the service fails at import (P1). Add the
CultLib root package.json/package-lock.json and
scripts/run-typescript-workspaces.mjs so the deploy host can build
CultLib's TS dist/ itself, and carry packages/cultmesh-ts and
packages/cultmesh-browser alongside the two packages already archived.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 15:54:11 +02:00
Meta Vens
5a015d9d9c REC-014: cut dead Odin dump examples and dangling Gjallar npm scripts
Deletes crates/odin-core/examples/dump_move_tracker_health.rs and
dump_provider_endpoints.rs (no in-swarm caller: full-corpus rg for both
executable names found only their own usage strings, plus the two sibling
Odin worktrees that carry byte-identical copies). Removes package.json's
gjallar:build/gjallar:start scripts, which run `cargo build/run -p
gjallar-daemon` — no such Cargo package exists in this workspace (members:
sleipnir-daemon, odin-core, odin-daemon) or in the sibling Gjallar repo,
which is a C#/.NET executable (src/Gjallar/Gjallar.csproj), not a Rust
package.

Kill attempts that failed to find a consumer:
- rg -n "dump_move_tracker_health|dump_provider_endpoints" across all of
  F:/Projects excluding target/node_modules/.git: only the examples' own
  usage strings, the census docs, and the two other Odin worktrees.
- rg -n "gjallar:build|gjallar:start" across all of F:/Projects: only
  Odin's own package.json (this repo + 2 worktrees) and census docs.
- Collision check: git diff --stat origin/main...codex/cultmath-cutover and
  ...codex/ygg-ghostlight-continuity over these paths: empty, no in-flight
  work touches them.
- state/map.yaml and notes/*.md: no reference to either example or the
  gjallar npm scripts.

Not touched: the root Cargo.toml exclusions for vendor/cultcache-rs and
vendor/cultnet-rs named in REC-014 are already gone — removed by commit
6575de4 ("Drop the workspace excludes for vendor trees that no longer
exist"), prior to this pass. That part of REC-014 is moot.

REC-014

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 14:00:34 +02:00
Meta Vens
aaaa8ed7b0 A stored presence that no longer authenticates is stale, not fatal
On 2026-09-11 a provider's continuity restart (raven-muninn, new
activation) left its previous presence in Odin's store. Odin treated a
stored presence that failed authentication under an authority its own
correlation still named as tampering and exited; every continuity
restart read the same record at startup and died the same way, three
times, and Idunn gave up on odin. The rendezvous was dark for the whole
Verse over one provider's evidence. It is now recorded as a
stored-presence-not-current disagreement and logged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 14:31:01 +02:00