Skip to content

Genesis: Implement runtime growth pipeline (ICurrencyTransactionListener + flush worker + ISeedEvolutionListener) #720

Description

@DonLoquacious

Genesis Runtime Growth Pipeline — Stubs #1-#3

Source: docs/plugins/GENESIS.md § Stubs & Unimplemented Features (#1, #2, #3)
Blocks: Divine divinity generation, wallet-as-universal-counter pattern, entity awakening lifecycle
Related: #712 (Seed bond propagation), #713 (Seed batch growth events), #714 (external seed adoption)

Summary

Genesis has a fully implemented API surface (19 endpoints, 0 stubs) with templates, entity CRUD, bonds, capabilities, compression, and cleanup. But the runtime pipeline that connects currency wallet credits to seed growth to cognitive awakening is not implemented. Three tightly-coupled stubs form this pipeline and should be implemented as a single unit.

The Pipeline

Currency wallet receives credit (from game engine, quest reward, god-actor, autogain)
    ↓
Stub #2: ICurrencyTransactionListener (DI, L2 co-located)
    Genesis checks in-memory wallet map (~microseconds)
    Buffers matched credits in growth accumulator (ConcurrentDictionary)
    ↓
Stub #1: GenesisGrowthFlushWorkerService (BackgroundService)
    Drains accumulator every GrowthFlushIntervalSeconds (default: 5s)
    Batch-calls ISeedClient.RecordGrowthBatchAsync per entity
    One Seed lock acquisition per entity per flush (not per credit)
    ↓
Stub #3: ISeedEvolutionListener implementation
    Receives phase transition notifications from Seed
    Dormant → Stirring: spawns Actor with ABML behavior from template
    Stirring → Awakened: creates Character in system realm, binds Actor
    Publishes genesis.entity.phase-changed event
    Creates deferred bond Relationships at Awakened stage

What Each Stub Requires

Stub #2: ICurrencyTransactionListener

  1. New DI interface in bannou-service/Providers/ICurrencyTransactionListener.cs:
    ICurrencyTransactionListener
        OnCurrencyCreditedAsync(walletId, currencyCode, amount, newBalance, ct)
        OnCurrencyDebitedAsync(walletId, currencyCode, amount, newBalance, ct)
    
  2. Currency dispatch: lib-currency discovers IEnumerable<ICurrencyTransactionListener> via DI, dispatches after wallet mutations (same pattern as ISeedEvolutionListener, ICollectionUnlockListener)
  3. Genesis implementation (GenesisCurrencyTransactionListener): Singleton, checks in-memory ConcurrentDictionary<Guid, GenesisWalletMapping> for walletId, buffers matched credits in growth accumulator
  4. Wallet map population: Populated at startup from MySQL, invalidated via self-subscription to genesis.entity.created/genesis.entity.deleted events (the event handlers in GenesisService.Events.cs are already registered as no-op placeholders for this)

Stub #1: GenesisGrowthFlushWorkerService

  1. BackgroundService following canonical polling loop pattern (T6)
  2. Drains growth accumulator, groups by entityId
  3. For each entity: loads template from cache, applies growth mappings (amount × ratio, filtered by direction), calls ISeedClient.RecordGrowthBatchAsync
  4. Config properties GrowthFlushIntervalSeconds and StartupDelaySeconds already exist in schema (unreferenced)
  5. Telemetry spans per cycle, per-item error isolation, worker error publishing

Stub #3: ISeedEvolutionListener

  1. Singleton implementation of ISeedEvolutionListener (interface already exists in bannou-service/Providers/)
  2. OnPhaseChangedAsync: loads entity by seedId (reverse lookup via entity query), loads template, checks awakening thresholds:
    • Stirring phase: spawn Actor via IActorClient with template's behavior document reference
    • Awakened phase: create Character in system realm via ICharacterClient, bind Actor via IActorClient.BindCharacterAsync, create deferred bond Relationships
  3. Updates entity model with ActorId, CharacterId, CognitiveStage
  4. Publishes genesis.entity.phase-changed event

Why These Are One Unit

Scale Considerations

At 100K+ entities with genesis-managed wallets:

  • ICurrencyTransactionListener adds ~30ms of ConcurrentDictionary lookups per Currency autogain tick (vs ~9s with Redis)
  • Batched flush reduces Seed lock acquisitions from one-per-wallet-credit to one-per-entity-per-flush-interval (10-20x reduction)
  • 5-10 second delay between wallet credit and seed growth is invisible for entities whose phases span hours/days

Also Untracked (Lower Priority, Separate Issues)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions