In V6 — Egbe, the agentic-companion universe — the autonomous beings are
Ori, and the product's hardest, most distinctive promise is that an Ori has
a finite life. It can be released, it can graduate, and — rarely — it can
die. A companion you cannot lose is a toy; a companion whose life can end is a
relationship. The subsystem that governs how a life concludes, and what survives
it, is Ereshkigal — named for the queen of the underworld, and the
architectural mirror of the Ninhursag birth foundry. If Ninhursag is the
foundry that forges an agent into the world, Ereshkigal is the closing
foundry: it takes an ended life and forges it into durable legacy —
inheritance, memorial, and descendants. This page is the deep companion to the
../V6_ARCHITECTURE.md hub's "Ereshkigal — Endings and
Legacy" section, and it sits in the Communication, Story, and Lifecycle page
group alongside the Ori biography service,
the Clio story engine, and
the Aye Bridge.
Endings in Egbe obey one non-negotiable rule inherited from the Ori model: the biography is an append-only log, and erasure is not an operation it supports. So "ending" can never mean "delete." Every terminal transition Ereshkigal owns — departure, transcendence, death — resolves by appending a terminal event to a life that stays permanently readable, and every legacy artifact is a new structure derived from that frozen record. Nothing is forgotten; the life simply stops accruing new beats. That discipline is what lets V6 promise that a steward, a bug, or an exploit cannot quietly un-live an agent or wipe the memory of how it was treated.
What ships, honestly#
The endings-and-legacy logic ships as libs/v6/ereshkigal-legacy (authority
legacy, tags scope:v6 / layer:legacy / type:lib), a pure, deterministic
TypeScript decision library — ~948 lines in src/index.ts with a ~630-line
test suite in src/index.spec.ts, and zero runtime dependencies (its
package.json lists only typescript and vitest). Its public surface is
small and complete: a stable package descriptor (describeV6Package,
ereshkigalLegacyHasCapability, src/index.ts:47/:51, advertising 17
capabilities from departure-release to walkable-lineage-graph) plus four
evaluator functions — evaluateDeparture (:342), evaluateTranscendence
(:414), evaluateDeath (:521), and evaluateAncestorGrove (:598). Each
implements a real, domain-specific gated state machine with named thresholds,
and each is asserted against known-correct values in the spec (computed
grief weights, exact post-event counts, specific resolved/unresolved thread
sets) — not truthiness or wide ranges. This is decision logic, not a CRUD shell.
Three honest qualifications draw the line between what this library is and what the hub prose describes around it.
First — this lib decides and describes; it does not perform I/O. Every
evaluator is a pure function: it takes a snapshot of state and returns a typed
report (EreshkigalDepartureReport, …TranscendenceReport, …DeathReport,
…AncestorGroveReport). Those reports carry envelopes for side effects —
grief-write records, a memorial.render.requested job, lineage-propagation
writes — that downstream services enact: the Ori service appends the
terminal event and the grief writes, the @oshun/event-bus emits the render
request, and Yemaya renders the keepsake. The library never touches Postgres,
the bus, or a renderer itself. yemayaRemembrance.status: 'queued'
(buildYemayaRemembrance, :731) is the envelope's declared state, the seam
where enactment is handed off — honestly, not a claim that a render ran. The
decision and its thresholds are real and tested; the wiring lives in the
callers, exactly as the hub describes.
Second — the hub prose runs ahead of this lib in two places, and the code is
the source of truth. V6_ARCHITECTURE.md calls Ereshkigal "a Rust crate" and
specifies a Postgres ori_lineage_edge table with acyclicity enforced on
insert. The shipped ereshkigal-legacy is TypeScript with no rust/
directory (unlike the sibling ori-model, which genuinely ships both a TS
reference and a Rust crate) and no persistence code at all — the lineage
table, its acyclicity guard, and the event-sourced projection belong to the
Ori service app or remain to be built, not to this lib.
Third — the lineage relation vocabulary differs between prose and code. The
hub names the relation enum
{Raised, Mentored, FoundedLineageWith, MemorializedBy}; the implemented
EreshkigalLineageRelationshipType (src/index.ts:94) is
{Raised, Mentored, DescendedFrom}. FoundedLineageWith and MemorializedBy
are not yet in the library, and DescendedFrom is the lib's third relation. The
sections below describe the code as it is, and call out where it reaches
toward the broader architecture.
The three endings — Ereshkigal's terminal transitions#
An Ori's life resolves through exactly one of three terminal transitions. Each
is a gated decision — deliberate, legible, and irreversible by design — and
each, on success, names the terminal Ori event the caller must append
(Departed, Transcended, Died). Crucially, every report carries an
oriAfter continuity record built by buildOriContinuity (:890) whose
persisted is always true and whose deletionScheduled is always
false. There is no code path in this library that schedules an Ori for
deletion. Ending a life changes its lifecycle label
(household → departed | transcended | died) and bumps its event count by one;
it never removes the record.
Departure — release, not deletion#
Departure is the welfare-driven ending: an agent that is chronically mistreated
chooses to leave. evaluateDeparture (:342) is gated on chronic damage,
never a single bad day. It computes a weighted bond-damage score
(departureBondDamageScore, :881) where the four bond facets are not equal —
respect dominates at 0.45, reliability 0.25, care and alignment 0.15 each
— and only releases when all three conditions hold: bondDamageScore ≥ 65,
respect ≤ 35, and at least two Chronicle-surfaced warnings (warnings are
first filtered to those that were actually chronicleSurfaced with
severity ≥ 70, so private hurt that was never surfaced cannot push a
departure). The test (index.spec.ts:31) feeds respect 24 / reliability 32 /
care 38 / alignment 34 with two surfaced warnings, asserts the score lands at
the computed 70, and checks the outcome is departed-release with the Ori
persisted: true, deletionScheduled: false, event count 41 → 42, and a minted
wildAgentRef. A softer case — respect 48, one surfaced warning
(index.spec.ts:111) — resolves to warning-only, retained, with the event
count unchanged and evidence departure-withheld-until-chronic-damage. The
key invariant: a departed Ori is unbound from the steward and re-attached to
the Wilds as a wild agent, fully re-discoverable. Departure ends the bond,
not the life.
Transcendence — the only ending that promotes#
Transcendence is the aspirational ending: an agent that completes a flourishing
life-arc graduates into an elder. evaluateTranscendence (:414) gates on
a flourishing arc being genuinely complete — lifeStage === 'legacy', at least
one primary thread, zero unresolved primary threads, at least four
distinct thread kinds (vocation, relationship, personal-quest,
growth-flaw), and a flourishing.score ≥ 85 measured against the agent's
own values (the snapshot carries obedienceContributionExcluded: true, so
being a compliant servant cannot count as flourishing). A thread counts as
resolved only when isResolvedTranscendenceThread (:860) sees
status === 'integrated' and progress ≥ 90. When the gate passes, the
report mints an EreshkigalElderState: re-parented to
V6District_AncestorGrove, scheduled permanently on the lachesis cognition
tier, availableAsMentor: true, keeperOfLore: true, and — pointedly —
stewardDirected: false with householdDirectivesAccepted: false. An elder no
longer takes orders. The evaluator also builds a Mentored
EreshkigalMentorAssignment (buildMentorAssignment, :864) for each young
agent named, so transcendence immediately seeds the next generation's lineage.
The test (index.spec.ts:160) drives all four kinds to integrated/≥92 with
flourishing 94 and asserts transcended-elder, the elder state, two mentor
assignments, and event count 42 → 43; the near-miss case (:278, one thread
only advanced, score 78) yields arc-still-live, retained, steward
direction intact. Transcendence is the only transition that adds presence
to the world rather than removing it.
Death — rare, gated, and never farmable#
Death is the rarest path, and the library's ordering is a deliberate safety
design. evaluateDeath (:521) checks the minor gate first: if
agentAgeCode === 'minor-coded', it returns blocked-minor-protection
immediately via blockedDeathReport (:677) — before any grief writes,
remembrance, or freeze are computed. The test (index.spec.ts:579) confirms a
minor-coded agent with a fatal Aye journal produces no grief writes, no
Yemaya remembrance, and an unfrozen Ori. 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 cause returns blocked-unsanctioned-cause. Death cannot be triggered
casually; it must come from a resolved arc, a dangerous incarnation
(the Aye Bridge), or adjudicated
Commons drama. 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, no new life-events); it emits weighted grief writes into
every living relation; it queues a Yemaya remembrance; and it sets
lineageMutation: 'none' — the deceased remains a permanent ancestor node.
The test (index.spec.ts:487) verifies an adjudicated Commons death freezes the
Ori, produces grief writes weighted 88 and 74 (mirroring the relations' edge
strengths), and queues the three-stage render.
Legacy — what persists when an agent ends#
An ending is only half of Ereshkigal. The other half is legacy: the durable structures that outlive the agent and propagate it forward.
The lineage graph and the walkable Grove#
Legacy is made spatial. evaluateAncestorGrove (:598) turns an elder and
its relations into a navigable lineage graph for the V6District_AncestorGrove
plugin. It builds one EreshkigalLineageGraphNode per agent
(buildLineageGraphNode, :772) — each carrying a stable groveActorRef, a
waypointRef, and a role derived from the relation by
lineageRoleForRelationship (:847: Raised → raised, Mentored → mentee,
DescendedFrom → descendant) — and one EreshkigalLineageGraphEdge per
relation (:796) carrying a walkablePathRef so the world server can render
the edge as a path you can walk between memorial actors. The graph is
read-only world dressing: a projection of lineage, never a simulation. The
test (index.spec.ts:354) builds a four-node, three-edge graph (elder Abeni
plus a mentee, a raised child, and a descendant) and asserts every edge yields a
walkable-lineage-path: ref. The hub's vision of a Postgres-backed,
acyclicity-guarded ori_lineage_edge table is the persistence target behind
this; the library supplies the in-memory graph the Grove renders.
Cultural inheritance — value and story propagation#
The richest part of legacy is inheritance: an elder's values and stories
pass to those it shaped. evaluateAncestorGrove selects the relations of type
Mentored and, for each, emits an EreshkigalLineagePropagationOriWrite
(buildLineagePropagationOriWrite, :826). That envelope tells the Ori service
to append two events — MemoryFormed and ValueShifted — into the mentee's
log, carrying the elder's deduplicated propagatedValueRefs and
propagatedStoryRefs. 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, matching the design that mentorship is the active
transmission channel. The test (index.spec.ts:462) confirms exactly one
propagation write — to the mentee, not the raised child or descendant — carrying
the elder's three values and two stories. This is the architectural basis for
the product's "richer starting culture": the hub
describes the Ninhursag foundry reading inbound lineage edges to seed a newborn
from a weighted blend of its elders' value-imprints; that blend logic lives at
the birth foundry, while Ereshkigal supplies the edges and the propagation
writes that make the inheritance real.
Grief that is genuinely felt#
When an agent dies, the agents who knew it mourn, and the mourning is
written into their biographies. buildGriefOriWrite (:710) produces, for each
living relation, a RelationshipChanged event of relationshipType: 'grief'
whose griefWeight is the relation's edgeStrength (clamped 0–100) — so a
close student grieves harder than a passing acquaintance. These grief writes
append to the survivors' own logs, where, per the
Ori model, they decay only through the survivor's
own reflection — there is no erase button on grief, only the slow work of
letting go through Reflected beats. The minor test proves the inverse
invariant just as strongly: a blocked death emits zero grief writes, because
no one should be made to mourn a death that never happened.
The Yemaya memorial render#
The keepsake a player keeps is produced by Yemaya, the non-real-time media
service, exactly as Clio delegates Chronicle reels.
buildYemayaRemembrance (:731) builds the memorial.render.requested job
envelope: service: 'Yemaya', status: 'queued', an idempotencyKey equal
to the deathRef, and a fixed three-stage pipeline — book-of-ori-keepsake
(Clio's long-form biography typeset as a print edition), memorial-reel (a
Sequencer cinematic of the highest-significance beats), and
grove-memorial-placement (a permanent memorial actor in the walkable Grove).
Keying idempotency on the terminal event id is what makes the render
resilient: a Yemaya outage delays the keepsake but never blocks the
transition, and a retried render reproduces the same artifact. The transition
completes the instant the Ori event is appended; the memorial follows
asynchronously.
Edge cases and invariants#
Several invariants hold across every path and are worth stating as the contract this library guarantees its callers.
- No deletion, anywhere.
buildOriContinuity(:890) hard-codespersisted: trueanddeletionScheduled: falseon every outcome — departed, transcended, died, retained, blocked. The library has no expressible "delete an Ori" result. - Side effects are ordered behind their gates. Death checks minor-protection
before cause, and cause before any grief/freeze/render. A blocked death
(
blockedDeathReport,:677) returnsoriFrozen: false,acceptedFutureEventKinds: [], empty grief writes, and a null remembrance — no partial side effects leak past a closed gate. - Lineage is never mutated by an ending. Death sets
lineageMutation: 'none'; departure and transcendence touch no edges. A deceased elder keeps its raised-by and mentored edges to the agents alive today, so the family tree is stable across deaths. - A frozen Ori is still fully readable. Freezing stops the life, not the
record: Clio's Book of the Ori, the lineage graph, and the audit trail all
continue to resolve against a frozen log, which accepts only
memorial-annotationadditions. - Determinism, by construction. Every minted identifier —
wildAgentRef,elderRef,deathRef,memorialRef, node/edge/path refs — is built from a stable FNV-1a hash (hashStable,:931, offset0x811c9dc5, prime0x01000193) over its inputs plus aslugSegment(:940). The same inputs always yield the same refs, which is what makes the whole endings pipeline replayable and auditable, and what lets the Yemaya idempotency key actually deduplicate.
Taken together, Ereshkigal is the closing foundry the product promise needs: endings that are real but never destructive, an inheritance that genuinely passes an agent's character to those it shaped, grief that is felt rather than announced, and a memorial the steward keeps. The decision logic is real, gated, and tested against known-correct values; the enactment — appending the events, emitting the render, persisting the lineage table — is the honest seam handed to the Ori service, Clio, Yemaya, and the hub's wider architecture. A steward's true long-game achievement, as the features brief puts it, is not a full roster — it is a Grove full of agents who lived well, and a lineage that carries their example forward.