In Yoruba cosmology Aye is the visible world a soul travels out into and returns home from; Orun is the spirit-world it belongs to. V6 — Egbe, the agentic-companion universe — takes that literally. An agent's home is Orun, the persistent open world it lives in; the Aye Bridge is the gate through which one of these beings can step out of Orun and incarnate into another Oshun product version — a fighter in V2, a citizen in V3, an operator in V4, a companion in V5 — and come home changed, carrying back deeds, scars, skills, and relationships that are written permanently into who it is. This is the meta-hub promise realized in code: not a character export, but a continuous life lived across the whole game universe and remembered in one place.
The single architectural idea underneath the bridge is the same one that governs
the Ori biography service: the Ori is the truth;
a realm is a stage it is rendered onto. The full event-sourced biography never
leaves V6. What crosses a game boundary is a passport — a signed, governed,
destination-minimised envelope — and what comes back is an incarnation journal
that appends to the home log like any other life-event. The bridge owns the
minting, the per-destination translation, the round-trip integrity, and the
governance of that journey, and nothing else. This page is the deep companion to
the ../V6_ARCHITECTURE.md hub's "The Aye Bridge"
section; it sits in the Communication, Story, and Lifecycle page group
alongside the Ori biography service and
the foundry, endings, and legacy.
What ships, honestly#
The Aye Bridge is real, substantive, test-backed decision code — a pure
kernel, not a descriptor shell, and not a running federation service.
libs/v6/aye-bridge/src/index.ts is ~2,398 lines of dependency-free TypeScript
(its package.json declares only typescript and vitest as devDependencies,
and the source file imports nothing — it is fully self-contained), backed by
src/index.spec.ts at ~1,331 lines and nineteen it() cases. The
describeV6Package() descriptor declares authority 'bridge' and 37
capabilities, from passport-minting through
mid-incarnation-window-close-allowed. Everything the bridge decides —
minting and validating a passport, minimising it to a destination's needs,
adapting it into each realm's role, running the disconnection-and-duplication
round-trip eval, governing consent and minor-protection, and writing the return
journal back — is implemented with domain-specific logic and asserted against
known-correct values.
Three honest qualifications mark the seams. First, the bridge is a decision
kernel with injected boundaries: it never opens a socket or writes a database.
The Ori service that actually mints a passport is the injected
AyeBridgeOriPassportMintClient interface (mintOriPassport); the Ori service
that writes a journal back is AyeBridgeIncarnationJournalWriteClient
(writeIncarnationJournalReturn); persistence is the injected
AyeBridgeRoundTripJobStore / AyeBridgeGovernanceAuditStore. The library
ships InMemory* implementations of those stores for tests; the real
Postgres-backed apps/v6/egbe-ori-service and the live destination realms are
the execution side the kernel hands off to. Second, the four destination
realms are real translations but not yet a live wire:
adaptPassportForDestination() deterministically maps an agent into a V2
fighter / V3 citizen / V4 operator / V5 companion profile, and that mapping is
genuine and tested — but a passport landing inside a running V2–V5 build, and
that build producing a journal, is the cross-game integration that remains
partly spec. Third, the bridge does not directly import @oshun/ori-model
or @oshun/identity; it re-declares the passport contract structurally (the
AyeBridge*-prefixed interfaces) so it stays a leaf library, and the steward's
account binding lives upstream. The sections below say which is which.
The cross-game incarnation model#
Three authorities, and where the bridge sits#
V6 splits every agent across three authorities that own different things (the
hub's Mind / Body / Memory split): the Body (Egbe-World) owns what
physically happened, the Mind (Moirai) owns what an agent decides, and the
Memory (the Ori service) owns who the agent
is — independent of any world shard or destination realm. The Aye Bridge is the
fourth seam: it is the only component that lets the Memory authority be
projected past a game boundary and reconciled back. Because durable truth
lives in the Ori event log, incarnation is not a save-file migration — it is the
same identity, temporarily rendered elsewhere, then re-absorbed.
The biography log already speaks this language natively. @oshun/ori-model's
ORI_EVENT_TYPES includes Incarnated and IncarnationReturned
(libs/v6/ori-model/src/index.ts:43), with typed payloads: IncarnatedPayload
carries the incarnationRef, destinationRealm, passportRef,
capabilityMappingRef, and departedAt; IncarnationReturnedPayload carries
the journalRef, returnedAt, deedRefs, and consequenceRefs. The
projection handlers make the journey legible in current state: the Incarnated
handler sets currentIncarnationRef, and the IncarnationReturned handler
clears it again and records the return. A stint in another realm is therefore
not metadata bolted on the side — it is two ordered events in the one
append-only life.
The realm inventory and the per-destination adapters#
AyeDestinationRealm enumerates exactly four live destinations:
'v2-maya' | 'v3-lilith' | 'v4-odysee' | 'v5-oshun'. Each is owned by one
adapter in the destinationAdapters registry (index.ts:829), keyed by a
stable adapterId and a versioned capability-mapping fragment:
| Adapter | Realm | Role | Mapping fragment | Translates (excerpt) |
|---|---|---|---|---|
v2-fighter |
v2-maya |
fighter |
v2-maya:fighter |
personality→fighting-style, capability→movelist, values→refused-tactics |
v3-citizen |
v3-lilith |
citizen |
v3-lilith:citizen |
personality+vocation→civic-role, values→lilith-persona-policy |
v4-operator |
v4-odysee |
operator |
v4-odysee:operator |
capability→operator-class, bond→tac-plan-discipline |
v5-companion |
v5-oshun |
companion |
v5-oshun:companion |
personality→dialogue-wheel-voice, values→paragon/renegade lean |
These are deliberate, designed translations, not a generic copy. The same
cautious, reliable agent becomes a guarded-counterfighter in V2 (caution ≥
0.66 ⇒
tacticalPosture: 'cautious spacing, counterpunching, and low-risk confirms'),
a recon-support-operator in V4 (with
planningDisposition: 'conservative-contingency-planner'), and a
loyal-field-companion in V5 — all derived from the same trait vector and
bond ledger by the v2FighterProfile / v3CitizenProfile / v4OperatorProfile
/ v5CompanionProfile builders. getAyeDestinationAdapter() throws on an
unknown adapter, and assertPassportMatchesAdapter() refuses to load a passport
through the wrong realm
('Aye destination adapter v2-fighter cannot load passport for v3-lilith'), so
an agent can never be silently coerced into a realm it was not minted for.
The Ori passport#
Minting and validation#
On incarnation the bridge requests a passport from the Ori service through
mintPassportFromOriService(request, oriService). The Ori service returns an
AyeBridgeOriServicePassport — an AyeBridgeOriPassportEnvelope
(schemaVersion: 'v6.ori.passport.1', an ori-passport-mint job with an
idempotencyKey) wrapping the identity core, the provenance bundle, the
personality model, the current ranked values, a destination-scoped capability
profile, and the bond ledger, plus a detached isisSignature. The bridge then
runs validateOriServicePassport() and throws if the envelope is not
complete ('Ori service passport failed Aye Bridge mint validation').
Validation is seven hard checks, every one of which must hold: identity carried
(oriId matches in both the envelope and the identity core), provenance carried
(bundle status: 'verified', signed by
ISIS_AYE_BRIDGE_SIGNER_REF = 'isis-signer:aye-bridge:production'), personality
and current values present, the capability profile scoped to this destination
realm and mapping with at least one skill, the bond ledger keyed to the
requesting steward, and the Isis signature consistent —
passport.isisSignature.chainHash must equal input.governance.chainHash. A
spec case proves an unsigned passport is rejected outright. Note the
schema-prefix discipline: the passport and the journal carry v6.ori.* schema
versions because the Ori owns those contracts, while the governance,
minimisation, and round-trip results carry v6.aye-bridge.* versions because
the bridge owns them.
Data minimisation by construction#
A destination realm must never see more of an agent than it needs to render it.
minimisePassportForDestination(passport, adapterId) computes the required
field set per adapter (destinationNeededPassportFields()) and emits an
AyeBridgeDestinationMinimisedPassportPayload that carries only those fields.
The excludedFields list is explicit and code-fixed (index.ts:926): the user
and project metadata, the canonical (internal) name, the appearance seedId and
seedHash, the personalityModelId, every value's sourceEventRefs, and the
bond ledger's historyRef and lastChangedByEventId are all stripped before
any adapter sees the payload. The result's destinationNeededDataOnly flag is
true only when no required field is missing and no unnecessary field
leaked — and the inverse path is tested too: emptying a passport's
includedSkillRefs makes the V2 fighter minimisation report
destinationNeededDataOnly: false and surface missing:capabilities.skillRefs,
so a thin passport fails loud at the gate rather than crossing half-formed. V3
is the one adapter that additionally needs capabilities.knowledgeDomainRefs (a
citizen has vocations); the combat realms need bond.facets (to compute call
reliability and plan discipline) but not knowledge domains. Minimisation is, in
other words, per-destination need, not a fixed redaction.
Recognizability — the same agent in every realm#
Minimisation strips identity internals but must preserve identity
legibility: the steward has to recognise their agent on the other side.
recognizabilityProfile() extracts the stable anchors — display name,
appearance asset-manifest ref, the non-zero trait anchors with human
translations (caution ≥ 0.66 ⇒
'low-risk choices across combat, planning, and counsel'), the ranked values
rendered as hard boundaries vs. preferences, and bond anchors. The adaptation's
consistencyEvidence array binds the agent's oriId, appearance, top values, and
top traits, and the spec asserts that one cautious agent named Abeni adapted
into all four realms yields a single recognizability identity
(new Set([...identityDisplay]) === {'Abeni'}) while producing four different
role-correct profiles. That is the cross-realm contract: recognizably itself
everywhere, mechanically re-expressed each place.
The round-trip: integrity under fault and concurrency#
An incarnation is a tracked job, and the bridge's hardest promise is that an
agent is never lost between worlds and never duplicated.
startIncarnationRoundTrip(request, store) first refuses a second active
journey for the same Ori —
listRoundTripJobsForOri(oriId).find(isActiveRoundTripJob) throws
'Active Aye round-trip already exists for Ori …' — then writes a job in status
'destination-active' whose activeCopies records exactly one Orun reservation
and one destination actor, plus an immutable orunStateSnapshot (checkpoint
ref + content hash) taken before departure. The job status machine is
prepared → destination-active → returning → returned | aborted.
The adversarial case is a destination that vanishes mid-incarnation.
handleDestinationUnreachableDuringIncarnation(fault, store) flips the job to
'aborted', nulls the destinationActorRef, and stamps the fault — then runs
validateRoundTripIntegrityAfterFault(), which must satisfy all five invariants
or the handler throws: orunStatePreserved (the snapshot is byte-identical
before and after), agentNotLost (exactly one Orun copy, with checkpoint and
state hash intact), agentNotDuplicated (one Orun copy, zero destination
copies, and zero remaining active jobs for the Ori), cleanAbort, and the
composite complete. The spec drives a V4 gateway timeout and asserts
activeOrunCopyCount: 1, activeDestinationCopyCount: 0, and a clean abort.
The Orun-side state was reserved, never surrendered, so the worst case is a
cancelled trip, not a lost being.
When a journey succeeds, writeIncarnationJournalBackToOri(request, oriService)
asks the Ori service to append the return and then validates the result through
eight checks (validateIncarnationJournalWriteBack): deeds, relationships,
skills, and harm all written into the journal; a returnEventWritten check that
the appended event is genuinely an IncarnationReturned with the right ids and
that the journal's sourceEventRefs contain both the Incarnated and
Returned event refs; a returnWindowValid check that
returnedAt > departedAt; a provenanceSigned check (Isis-signed journal with
chain hash and receipt); and oriChanged, which is true only when the return
event was written and the delta is non-empty. If any check fails the write
throws ('Incarnation journal write-back failed Aye Bridge validation'). The
returned AyeBridgeIncarnationReturnDelta is exactly what makes "the agent
returns to Orun changed" a concrete, inspectable object rather than a slogan —
and a spec loop runs the full write-back for all four live realms.
Incarnation governance — consent, policy, and minor-protection#
Incarnation is opt-in per agent and per steward, and
evaluateIncarnationGovernance(request, auditStore) is the gate that proves it.
It begins by asserting the request matches the passport (same destination realm,
same steward as the bond ledger), then evaluates four concerns and records every
one to the audit store.
- Weighted agent consent.
evaluateAgentConsent()is a real scoring formula, not a boolean:weightedConsentScore = 0.45·valuesAlignment + 0.35·bondAverage + 0.20·stateReadiness, accepted only when the agent's signal is not'unwilling', the score clears athresholdof0.66, and a timestamp is present.coercionDetectedis true when a steward override is requested over a non-accepted consent — the agent's refusal is a first-class, logged fact. - Policy continuity.
validatePolicyContinuity()requires that both an Isis and a Lilith policy bundle ride inside the passport and that every destination policy evaluation references a bundle the passport carries — so the destination cannot make a V6 agent do what V6 policy forbids, because the policy travels with the agent. - Minor-protection.
validateMinorProtection()blocks amature-rated destination whenever the subject is minor-coded (a minor steward or a minor-coded agent) and requires the passport'sminorProtectionRefto match. - Destination-policy enforcement. Any destination action evaluated as
'blocked'forces the overalldecisionto'blocked'.
The decision collapses to 'blocked' if any blocking reason exists, else
'coerced-approved' if coercion was detected, else 'approved'. Coercion and
blocks route to Themis (themisDisputeForGovernance) and coercion
additionally triggers a welfare review (welfareReviewForGovernance), each
emitting a typed routing object and an audit entry. The spec proves all four
paths: a willing consensual approval (one incarnation-consent audit entry); an
unwilling agent overridden ('coerced-approved', welfare review + Themis
dispute
- coercion audit entries); a
target-noncombatantaction blocked by Lilith destination policy; and a minor-coded agent blocked before a mature V5 mission. This is the same "sovereignty bounded by an inviolable core" posture V7's governance plane describes — the destination renders the agent but never owns its safety floor.
Campaign windows — cross-game programming#
The bridge also models scheduled cross-game events. An AyeCampaignWindow
(kinds 'v2-tournament-season' | 'v5-story-chapter' | 'v4-operation-series')
declares a published opensAt/closesAt schedule, a realmOptIn flag, and an
activeMidIncarnationAllowedToFinish flag. evaluateAyeCampaignWindow() sets
openToV6Agents only when the window is open, the realm has opted in, the
adapter matches the destination, and the schedule is well-formed
(publishedAt ≤ opensAt < closesAt); startCampaignIncarnationRoundTrip()
refuses a new departure through a closed or wrong-realm window. The humane
detail is alreadyMidIncarnationAllowedToFinish: when a window closes, an agent
already inside a campaign finishes its run, while a fresh departure after the
bell throws — a tournament season can end without yanking a fighter out of its
final match.
How identity composes — shared @oshun/identity and the V7 reuse#
The steward who sends an agent across the bridge is a V1 platform account.
The Aye Bridge library itself holds no identity logic — it carries stewardRef
and userId strings and trusts that the account was authenticated upstream by
@oshun/identity (libs/shared/identity): the shared JwtService, the
authenticate / hasPermissions middleware, the mTLS peer-identity helpers,
and the v2-account-binding module that already binds entitlement-bearing
contexts onto the one account root. As the hub puts it, because the Ori is the
source of truth, the steward's whole household is intrinsically cross-platform
— there is no per-platform save to reconcile. The minted passport carries the
platform-authoritative identity reference across a version boundary while the
destination only ever touches the minimised projection. The platform foundation
this composes is documented in
../../platform/auth-identity.html.
That the Aye Bridge is the canonical cross-version seam is confirmed by V7
reusing it wholesale. V7's libs/v7/substrate-bridge re-implements the passport
mint in native Rust but stamps every envelope
generated_by = "@oshun/aye-bridge" and
v6_aye_bridge_package_ref = "libs/v6/aye-bridge", naming this library the
contract owner; its Cargo.toml carries real path dependencies on
apps/v6/egbe-ori-service and libs/v6/ori-model/rust, so V7's character store
compiles in the V6 Ori event store rather than stubbing it. A V7 character
is, at root, a V6 Ori, and it crosses realms through this bridge's model — the
same four v2-fighter … v5-companion adapters, plus one realm-to-realm
federation corridor V7 adds on top. The full treatment is in V7's
Eunomia Governance & the Ori Cross-Version Bridge.
Where to read next#
- The Ori biography service — the Memory authority
whose append-only log is the single source of truth the passport projects from
and the journal writes back into; the upstream owner of the
v6.ori.passport.1andv6.ori.incarnation-journal.1contracts. - The foundry, endings, and legacy — how an
agent enters the world and how it leaves it; a fatal outcome returned in an
Aye incarnation journal is one of the three sanctioned causes of a gated
Diedtransition, so the bridge and the endings layer share an edge. - Auth & Identity — the shared
@oshun/identityJWT/OAuth foundation the steward account and the passport's identity reference compose across every Oshun version.
Related#
- Section hub: ../V6_ARCHITECTURE.md
- Real code cited here:
libs/v6/aye-bridge/src/index.ts(the bridge kernel),libs/v6/aye-bridge/src/index.spec.ts(the behavior suite),libs/v6/ori-model/src/index.ts(theIncarnated/IncarnationReturnedbiography events and projection handlers), andlibs/shared/identity/src(the V1 platform identity foundation the steward account composes).