Egbe Companions · Features

Guiding Fate, Legacy & Story

A focused page within the Egbe Companions Features documentation. The full map and every sibling page live in the Features hub.

5sections12 minread1diagram

On this page

V6 — Egbe, the agentic-companion universe — makes a wager most companion games never dare: that an agent's life is worth guiding, worth ending, and worth reading. The three are one promise. You do not script an Ori's life — you shift its probabilities, by what you set it toward, who you introduce it to, and what it watches you do. That accumulated life eventually resolves: an agent can leave you, graduate into an elder, or — rarely — die, and each ending leaves something durable behind. And because the world keeps moving while you are gone, someone has to turn the pile of machine-recorded life-events into a story a human actually wants to read, without ever lying about what happened. This page is about that whole arc — how a steward guides a fate, what survives an agent's end as legacy and inheritance, and how the emergent story of a life is told. It draws three named subsystems together: the Ori model that records a fate, Ereshkigal that governs endings, and Clio that narrates them. For where this sits in the whole product, start at the hub: ../V6_features.md.

What ships, honestly#

These three concerns ship as three real, deterministic, dependency-free TypeScript libraries, each tested against known-correct values, each fronting an honest seam where enactment is handed off. Nothing here fabricates a result it did not compute.

  • The fate substrate is real — libs/v6/ori-model. An agent's evolving fate is not a hidden score; it is an append-only event log. OriEventLog (src/index.ts:550) and applyOriEventToProjection (:1068) fold typed events — ValueShifted, ArcAdvanced, Crossroads, BondChanged, and the three terminal events — into a projection. Value drift is bounded (applyOriTraitDrift, :1656) and values are deterministically re-ranked (rankOriValues, :1619). This is the loom every steward action is woven into.
  • Endings are real, gated decisions — libs/v6/ereshkigal-legacy. A ~948-line pure decision library (authority legacy) with four evaluator functionsevaluateDeparture (:342), evaluateTranscendence (:414), evaluateDeath (:521), evaluateAncestorGrove (:598) — each a gated state machine with named thresholds, each asserted in 8 Vitest cases against computed grief weights and exact post-event counts. Honest seam: this library decides and describes; it performs no I/O. Its reports carry envelopes (grief writes, a memorial.render.requested job, lineage-propagation writes) that downstream services enact. yemayaRemembrance.status: 'queued' (:731) is the declared hand-off state, not a claim a render ran.
  • The story engine is real — libs/v6/clio-story. A 1,701-line library (authority story, 20 capabilities) whose algorithms — significance ranking, the returning-player Chronicle, emergent-arc surfacing, the Book of the Ori, narrative reconciliation — are pure functions over typed events, exercised by 12 Vitest cases. Its prose-polishing model is an injected, fail-loud seam (ClioNarrativeWriter, :605); the Rust "service" the hub sketches is today a thin health shell, as the architecture companion documents. The intelligence lives in the library.

One honest cross-cutting note carried by the Foundry companion: the hub prose calls Ereshkigal "a Rust crate" with a Postgres ori_lineage_edge table, and names a wider lineage vocabulary. The shipped lib is TypeScript, holds no persistence, and implements EreshkigalLineageRelationshipType = {Raised, Mentored, DescendedFrom} (:94). The sections below describe the code as it is.

Guiding a fate — the long game#

"Guide their fate" means shift the probabilities of a life, never script an outcome. The mechanism is concrete: every consequential thing a steward does becomes an event on the agent's Ori log, and the agent's future cognition reads the resulting projection. There is no separate "fate state" that can drift from what was actually recorded.

The fate is the value vector, and it is the agent's own#

A steward's deepest channel of influence is example — the Black & White lesson. Observed steward behavior reweights a watching agent's values, and that reweighting is a real, bounded computation, not a vibe. A ValueShifted event (ValueShiftedPayload, src/index.ts:150) carries a currentRank, the causeEventRefs that justify it, and optional traitDeltas. When applied, applyOriTraitDrift (:1656) moves the personality trait vector — but clamps the cumulative drift per season to ±ORI_TRAIT_DRIFT_MAX_PER_SEASON_BASIS_POINTS (= 500, :25). A steward cannot rewrite an agent overnight; influence is gentle and cumulative, strong during rearing, slow for adults. The values themselves are re-ranked deterministically by rankOriValues (:1619), tie-broken by name so the same history always yields the same priorities.

This is why flourishing is measured against the agent's own values, not your obedience. When Ereshkigal later judges whether a life completed, evaluateTranscendence reads a flourishing snapshot whose obedienceContributionExcluded: true flag (ereshkigal-legacy/src/index.ts:156) is structurally enforced — a compliant servant cannot score as flourishing. A steward is "scored," in the Chronicle's reckoning, on whether their agents became themselves.

Goal-arcs the agent owns#

Beyond a single objective, a steward sets a goal-arc — a multi-stage ambition the agent owns. Each advance is an ArcAdvanced event (ArcAdvancedPayload, :183) carrying goalArcRef, fromStageRef, toStageRef, and the supportRefs (gifts, introductions, mentorship) that helped. The projection handler (:916) updates arcState.currentStageByArc, so an agent's live arc-stage is always a read over what actually happened. The steward supports the arc through objectives, gifts, and introductions — and through not over-managing it. An arc the player drives every step of is the player's arc; an arc the agent owns is the agent's fate.

Crossroads — the heartbeat of guidance#

A Crossroads is the recurring, legible moment where guidance is real and autonomy is also real. It is a first-class event (CrossroadsPayload, :190): a prompt, the optionRefs open to the agent, a stewardCounselWindowEndsAt deadline, and a resolutionRef that is null until the agent decides. The agent holds, within reason, for its steward's counsel — but whether it waits is weighted by the bond. A steward with deep Respect bond is genuinely consulted; a steward with poor Respect finds the agent has already decided before they arrive. Crossroads carry the second-highest significance weight in the entire story engine (88, below only Died/Transcended), which is the system's way of saying: the choices you are invited into are the spine of the story.

When a life ends — endings and legacy#

An Ori's life resolves through exactly one of three terminal transitions, each a deliberate, irreversible-by-design decision. The non-negotiable rule inherited from the Ori model is that the biography is append-only — "ending" can never mean "delete." Every Ereshkigal report carries an oriAfter continuity record built by buildOriContinuity (:890) whose persisted is always true and deletionScheduled always false. There is no expressible "delete an Ori" result in the library. The diagram below traces a fate from its recorded events, through the gate that ends it, to the legacy it leaves and the story Clio tells.

flowchart TB subgraph fate["Guiding fate — @oshun/ori-model (append-only log)"] EV["ValueShifted · ArcAdvanced · Crossroads · BondChanged<br/><sub>steward influence, bounded & re-ranked</sub>"] end EV --> which{"life resolves —<br/>which transition?"} which -- "chronic bond damage" --> DEP["evaluateDeparture()<br/><sub>damage≥65 · respect≤35 · ≥2 surfaced warnings</sub>"] which -- "flourishing arc complete" --> TR["evaluateTranscendence()<br/><sub>stage=legacy · 4+ kinds · score≥85</sub>"] which -- "sanctioned cause" --> DTH["evaluateDeath()<br/><sub>minor-gate → cause-gate → effects</sub>"] DEP --> REL["departed-release<br/><sub>unbound → Wilds · Ori persists</sub>"] TR --> ELD["transcended-elder<br/><sub>Ancestor Grove · Lachesis · mentor</sub>"] DTH --> DIE["died-memorialized<br/><sub>Ori frozen · grief writes · Yemaya render</sub>"] REL --> LEG[("Legacy: walkable lineage graph ·<br/>value/story propagation · memorial")] ELD --> LEG DIE --> LEG DIE -. "terminal event" .-> CLIO ELD -. "terminal event" .-> CLIO LEG --> CLIO(["Clio — Book of the Ori,<br/>Chronicle, Yemaya keepsake"]) CLIO --> READER[/"the steward — reads the story"/]

Departure — release, not deletion#

Departure is the welfare-driven ending: a chronically mistreated agent chooses to leave. evaluateDeparture (:342) gates on chronic damage, never a single bad day. It computes a weighted bond-damage score (departureBondDamageScore, :881) where the facets are deliberately unequal — respect dominates at 0.45, reliability 0.25, care and alignment 0.15 each — and releases only when all three hold: bondDamageScore ≥ 65, respect ≤ 35, and at least two warnings that were actually Chronicle-surfaced with severity ≥ 70 (:355). Private hurt that was never surfaced cannot push a departure. On release the Ori is unbound from the steward and re-attached to the Wilds as a wild agent (wildAgentRef, :400), fully re-discoverable. Departure ends the bond, not the life: a softer case resolves to warning-only, retained, event count unchanged.

Transcendence — the only ending that promotes#

Transcendence is the aspirational ending and the clearest sign a steward stewarded well. evaluateTranscendence (:414) requires a genuinely complete flourishing arc: lifeStage === 'legacy', at least one primary thread, zero unresolved primary threads, at least four distinct thread kinds (vocation, relationship, personal-quest, growth-flaw), and flourishing.score ≥ 85 (:433). A thread counts as resolved only when isResolvedTranscendenceThread (:860) sees status === 'integrated' and progress ≥ 90. On success the agent becomes an EreshkigalElderState (:472): re-parented to V6District_AncestorGrove, scheduled permanently on the lachesis cognition tier, availableAsMentor: true, keeperOfLore: true, and — pointedly — stewardDirected: false, householdDirectivesAccepted: false. An elder no longer takes orders. It is the only transition that adds presence to the world rather than removing it, and it immediately seeds the next generation by minting a Mentored assignment for each young agent named (:464).

Death — rare, gated, and never farmable#

Death is the rarest path, and the library's ordering is the safety design. evaluateDeath (:521) checks the minor gate first: a minor-coded agent returns blocked-minor-protection immediately (:536) — before any grief write, remembrance, or freeze is computed. Only then does the cause gate run: isSanctionedDeathCause (:751) admits exactly three causes — life-arc-terminal, aye-fatal-journal, adjudicated-commons-event — and any other returns blocked-unsanctioned-cause. A sanctioned adult death (died-memorialized) does four things: it freezes the Ori (oriFrozen: true, acceptedFutureEventKinds: ['memorial-annotation'] — the log now accepts only memorial notes); emits weighted grief writes into every living relation; queues a Yemaya remembrance; and sets lineageMutation: 'none' — the deceased remains a permanent ancestor node. A frozen Ori is still fully readable; freezing stops the life, not the record.

Inheritance — what an ending passes forward#

Legacy is the other half of Ereshkigal, and it is what makes a steward's true long-game achievement "a Grove full of agents who lived well" rather than a full roster. Four channels carry an agent forward:

  • Cultural inheritance. evaluateAncestorGrove (:598) selects the Mentored relations and, for each, emits an EreshkigalLineagePropagationOriWrite (buildLineagePropagationOriWrite, :826) telling the Ori service to append MemoryFormed + ValueShifted into the mentee's log — so a mentee literally forms a memory of, and shifts its values toward, the elder who taught it. Raised and descended relations get the edge but not the value push: mentorship is the active transmission channel.
  • Grief that is genuinely felt. When an agent dies, buildGriefOriWrite (:710) writes a RelationshipChanged event of relationshipType: 'grief' into each survivor, whose griefWeight equals the relation's edgeStrength — a close student grieves harder than an acquaintance. The minor-protection test proves the inverse: a blocked death emits zero grief writes; no one mourns a death that never happened.
  • The walkable Grove. Each ending projects a navigable lineage graph — one node per agent, one edge per relation, each edge carrying a walkablePathRef (:821) so the world server renders it as a path you can walk between memorial actors. Legacy is made spatial.
  • The keepsake the steward keeps. buildYemayaRemembrance (:731) builds the memorial.render.requested envelope with status: 'queued', an idempotencyKey equal to the deathRef, and a fixed three-stage pipeline — book-of-ori-keepsake, memorial-reel, grove-memorial-placement. Keying idempotency on the terminal event id is what makes the render resilient: a Yemaya outage delays the keepsake but never blocks the transition.

Every minted identifier across these paths is a stable FNV-1a hash (hashStable, :931, offset 0x811c9dc5, prime 0x01000193), which is what makes the whole endings pipeline replayable and the Yemaya idempotency key actually deduplicate.

The emergent story — Clio#

A guided fate and a meaningful ending are nothing if no one reads them. Clio, the muse of history, turns the raw event log into a story — and its inviolable rule is that it never invents events; every word of narration is a read over the authoritative log.

That fate, endings, and story are one system is visible in a single function. eventTypeSignificance (clio-story/src/index.ts:1581) maps the life-event taxonomy to a fixed scale, and it is the ending hierarchy made numeric: Died 100, Transcended 96, Departed 92, Crossroads 88, down through ValueShifted 74 to Born 40. The story engine ranks an ending as the single most significant thing that can happen to an agent.

Significance ranking and the returning-player Chronicle#

When a player returns after any absence, createReturningPlayerChronicle (:487) assembles a digest. First rankChronicleEventsBySignificance (:445) scores every candidate against a curated five-factor rubric — event type 0.30, emotional weight 0.22, arc relevance 0.20, relationship impact 0.16, steward relevance 0.12 (:449) — with deterministic tie-breaks for total reproducible order. The ranked events are grouped by (agent, arc-thread) so each beat is one agent carrying one thread, then batched, and Clio models its own latency: estimateReadyMs against CHRONICLE_READY_BUDGET_MS = 3_500 (:50). A long absence flips the Chronicle from ready to streaming, returning the newest, most significant beat first so a returning player is oriented in under a minute and never buried.

The no-invention covenant, enforced loud#

The base beats are deterministic template prose. The model-narrated path (createReturningPlayerChronicleNarrated, :636) hands an injected ClioNarrativeWriter (the V6 mount supplies Iris) only that beat's Ori-log slice, then audits the result: any citedEventRef outside the allowed set throws ClioNarrationFabricationError (:614), and an empty narrative throws too (:665). The LLM may speak the life; it cannot invent one, and it cannot fake success. With no writer injected, the grounded template prose stands. This is V6's local copy of a fair-play covenant — the model narrates, it does not author.

Emergent-arc surfacing and the Book of the Ori#

The Chronicle is retrospective; surfaceEmergentArcPrompts (:683) is prospective. It reads the live stream for four kinds of signal — escalating-feud, forming-romance, struggling-agent, fitting-wild-agent — scored by genuinely kind-specific formulas (scoreEmergentArcSignal, :1465: a feud weights tension 0.32; a romance weights affinity 0.36 and inverts tension; a struggling agent weights welfare risk 0.42). Every surfaced prompt is typed tone: 'gentle', requiresImmediateAction: false, beforeConclusion: true (:271) — stories worth a glance, raised as invitations, never demands.

And generateBookOfTheOri (:722) is the long-form biography: a continuous read over an agent's whole log, chunked into chapters titled by bookOfOriChapterTitle (:1211) — a chapter with Died/Transcended is "Legacy," an opening with Born/Discovered is "Beginnings." Coverage is provably total (:744). When a life ends, createBookOfOriKeepsake (:1266) detects the terminal event and emits the Yemaya keepsake request — closing the loop with Ereshkigal's own remembrance pipeline.

Verification and where this connects#

Clio carries five drift verifiers (verify-v6-clio-*.mjs) that guard the named symbols and contracts while the Vitest specs own behavioral correctness; they roll up into the launch-blocking aggregate verify:v6 fate-legacy-clio-readiness, backed by V6/release/fate-legacy-clio-readiness.v6release.json (status: green, requiredBeforeLaunch: true, covering TODO sections 24–26: fate, endings, story).