import type { EngineModule, WorldState } from '@ai-rpg-engine/core'; import type { ItemCatalog, ItemChronicleEntry, ItemDefinition } from './types.js'; import { type GrowthMilestone } from './relic-growth.js'; /** Persisted module-state namespace key (world.modules[ITEM_CHRONICLE_STATE_KEY]). */ export declare const ITEM_CHRONICLE_STATE_KEY = "item-chronicle"; /** * The engine-computed growth summary for one item, persisted alongside the * raw entries. * * This exists so a consumer can read an item's tier WITHOUT calling * `evaluateRelicGrowth` itself. That matters for the ledger adapter, whose * equipment-snapshot.ts is type-only against this package by design (its * header: calling `evaluateRelicGrowth`/`getRelicTier` "would be a runtime * coupling this package's firewall forbids"). The engine computes; the * adapter reads plain data off a namespace — the same shape it already reads * `loadouts` with, via a locally-declared type and a duplicated string key. * * `milestoneCount` is the intended `relicVersion` axis. A raw chronicle-entry * count would advance an NFT's URI on an `acquired` event alone — churn, not * growth — whereas a milestone is by definition the moment an item's story * changed. XLS-46 NFTokenModify exists to record that an asset's state * evolved; "picked it up" is not evolution. */ export type ItemRelicSummary = { itemId: string; /** Growth milestones crossed — the meaningful-growth axis (the `relicVersion` source). */ milestoneCount: number; /** Coarse 0–3 tier, straight from `evaluateRelicGrowth`. */ tier: number; /** Epithet-resolved name for display ("Bloodied Cutlass"), or the plain name at tier 0. */ displayName: string; /** The current epithet, when one has been earned. */ epithet?: string; }; /** The persisted shape at world.modules[ITEM_CHRONICLE_STATE_KEY]. */ export type ItemChronicleModuleState = { /** Raw history, keyed by item id — the `recordItemEvent` shape. */ entries: Record; /** Engine-computed growth summary, keyed by item id. */ summaries: Record; }; /** * The recognition evaluator, INJECTED rather than imported. * * `evaluateItemRecognition` lives in `@ai-rpg-engine/modules`, which this * package may not import at runtime (modules is a devDependency here, and the * dependency runs the other way). equipment-core.ts already solved exactly * this with `EquipmentStatusOps` — status machinery is injected by the pack * "so this package keeps zero runtime dependencies" — and this is the same * pattern applied to the same problem. * * The shape is structural and matches `evaluateItemRecognition`'s signature * exactly, so a pack passes the function straight through with no adapter. * * NOTE the deliberate omission: `shouldRecognize`, the PROBABILISTIC gate, is * not used here and must not be. It needs a seeded roll drawn from the world * RNG, and consuming a draw would shift every subsequent roll in the run — * which is precisely the byte-identical replay guarantee this module exists * to keep. `evaluateItemRecognition` is rule-driven (provenance + faction * match), reads the world seed only as a pure hash input, and draws nothing. */ export type ItemRecognitionOps = { evaluate(equippedItems: ItemDefinition[], npcFactionId: string | undefined, itemChronicle: Record, tick: number, worldSeed?: number): ReadonlyArray<{ itemId: string; itemName: string; narratorHint: string; }>; }; export type ItemChronicleCoreConfig = { /** The pack's item catalog — the same one equipment-core is built with. */ catalog: ItemCatalog; /** * Optional per-item milestone overrides, keyed by item id. Falls back to * `evaluateRelicGrowth`'s slot-derived defaults (DEFAULT_WEAPON_MILESTONES * for weapons, DEFAULT_ARMOR_MILESTONES otherwise). */ milestones?: Record; /** * Optional recognition evaluator. Omit it and no `recognized` entry is ever * written — which also means `recognition-count` milestones stay unreachable, * and since DEFAULT_ARMOR_MILESTONES is only `age` + `recognition-count`, * armor then grows on age alone. */ recognition?: ItemRecognitionOps; }; /** * The full persisted chronicle, keyed by item id. `{}` when the namespace is * absent (nothing has ever been recorded in this world) or malformed — never * throws, never attaches. This is the value a checkpoint driver passes to the * ledger adapter's `equipmentSnapshotFromWorld(world, playerId, catalog, chronicle)`. */ export declare function getItemChronicle(world: WorldState): Record; /** Every engine-computed relic summary, keyed by item id. `{}` when absent. */ export declare function getRelicSummaries(world: WorldState): Record; /** One item's summary, or undefined when it has no recorded history. */ export declare function getRelicSummary(world: WorldState, itemId: string): ItemRelicSummary | undefined; /** * The name an item should be shown under right now — its earned epithet once * it has grown, else `fallback`. The one call a display surface needs. */ export declare function getItemDisplayName(world: WorldState, itemId: string, fallback: string): string; /** * Re-age every chronicled item against `tick` without recording anything. * * For callers that need current ages at a moment no chronicle write happened * to land on — principally a checkpoint driver about to snapshot for the * ledger, where a stale tier would be minted into an NFT URI. Takes the config * because milestones and catalog are the pack's, not the world's. * * No-ops (returning false, attaching nothing) on a world with no chronicle — * refreshing must never be what brings the namespace into being. */ export declare function refreshRelicSummaries(world: WorldState, config: ItemChronicleCoreConfig, tick: number): boolean; /** * item-chronicle-core — populates the item chronicle from real play so relic * growth manifests during a session. * * OPT-IN: a pack adds this to its module list to turn gear history on. Packs * that do not are byte-identical to the engine as it shipped without it. * Requires equipment-core, whose persisted loadout is how a kill is attributed * to the weapon that landed it. * * Records: * - `acquired` — the first time an item is picked up OR equipped * - `used-in-kill` — on `combat.entity.defeated`, against the killer's * currently-equipped weapon * - `recognized` — when an NPC sharing the wearer's zone reacts to * equipped provenance (requires `config.recognition`) */ export declare function createItemChronicleCore(config: ItemChronicleCoreConfig): EngineModule; //# sourceMappingURL=chronicle-core.d.ts.map