/**
 * Core data model for Hippo memory entries.
 * Based on the strength formula from PLAN.md.
 */
export declare enum Layer {
    Buffer = "buffer",
    Episodic = "episodic",
    Semantic = "semantic",
    Trace = "trace"
}
export type EmotionalValence = 'neutral' | 'positive' | 'negative' | 'critical';
export type ConfidenceLevel = 'verified' | 'observed' | 'inferred' | 'stale';
export type TraceOutcome = 'success' | 'failure' | 'partial' | null;
export type MemoryKind = 'raw' | 'distilled' | 'superseded' | 'archived';
/**
 * Timestamp invariant.
 *
 * All in-process writes of timestamp fields on `MemoryEntry` (`created`,
 * `last_retrieved`, `valid_from`) and on session-state types (SessionEvent,
 * TaskSnapshot, SessionHandoff, AssembledContextItem.createdAt, etc.) emit
 * canonical `Date.prototype.toISOString()` output: 24 characters, UTC,
 * milliseconds precision, trailing `Z` (e.g. `2026-05-06T09:55:49.123Z`).
 *
 * Caveat — markdown rebuild. `deserializeEntry` / `rebuildIndex` preserve
 * frontmatter timestamp strings as-is. Legacy markdown that recorded a
 * non-canonical offset (e.g. `2026-05-06T05:55:49-04:00`) round-trips
 * through SQLite without normalization, and DAG `earliest_at` / `latest_at`
 * caches are computed from those strings. Importers SHOULD normalize on
 * write; rebuild from drifted markdown is a known limitation.
 *
 * Byte-comparison sort (`<` / `>`) is chronological for any pair of
 * canonical UTC ISO strings. ~50× faster than `localeCompare` with no
 * semantic gain. F4 (v1.6.5) uses byte compare on `assemble`; if a future
 * import path admits non-canonical timestamps, the F4 sort and any
 * downstream chronological reasoning will need a normalization pass.
 */
export interface MemoryEntry {
    id: string;
    created: string;
    last_retrieved: string;
    retrieval_count: number;
    strength: number;
    half_life_days: number;
    layer: Layer;
    tags: string[];
    emotional_valence: EmotionalValence;
    schema_fit: number;
    source: string;
    outcome_score: number | null;
    outcome_positive: number;
    outcome_negative: number;
    conflicts_with: string[];
    pinned: boolean;
    confidence: ConfidenceLevel;
    content: string;
    parents: string[];
    starred: boolean;
    trace_outcome: TraceOutcome;
    source_session_id: string | null;
    valid_from: string;
    superseded_by: string | null;
    extracted_from: string | null;
    dag_level: number;
    dag_parent_id: string | null;
    descendant_count?: number;
    earliest_at?: string | null;
    latest_at?: string | null;
    /** v28: 1 when this summary row has at least one child invalidated,
     *  superseded, forgotten, or archived since it was last rebuilt. Cleared
     *  by E3's rebuildDirtySummaries during sleep. Always 0 for non-summary
     *  rows (dag_level !== 2; E5 widens to include 3). */
    summary_dirty?: 0 | 1;
    /** v28: ISO 8601 timestamp of the last successful rebuild for this
     *  summary, or null if never rebuilt. */
    last_rebuilt_at?: string | null;
    /** v28: monotonically-increasing counter of successful rebuilds for this
     *  summary. 0 for initial buildDag write; bumped by E3. */
    rebuild_count?: number;
    /** v28 (reserved for E5): ISO 8601 timestamp the level-3 entity profile
     *  was built. Only ever populated on dag_level=3 rows. */
    dag_level_3_built_at?: string | null;
    kind: MemoryKind;
    scope: string | null;
    owner: string | null;
    artifact_ref: string | null;
    tenantId: string;
    /**
     * F1 (v1.7.0): raw SQLite FTS5 bm25() score from the FTS path of
     * `loadSearchEntries`.
     *
     * Populated ONLY when ALL of the following hold:
     *   - `loadSearchEntries` was called with a non-empty query, AND
     *   - FTS5 is available (meta `fts5_available = 1`), AND
     *   - the FTS join returned at least one row (path 2 of `loadSearchRows`).
     *
     * `undefined` on every other path: empty query, FTS unavailable, LIKE
     * fallback, full-store fallback, `readEntry`, `loadAllEntries`, manual
     * upsert, deserializeEntry from markdown.
     *
     * SCALE: FTS5 bm25() is negative; lower = better match (ascending order).
     * NOT a drop-in for the JS-side BM25 in `src/search.ts` — that is a
     * different scorer (different tokenizer, different params, positive
     * scale). Treat `bm25_score` as provenance/rank metadata only.
     */
    bm25_score?: number;
}
export declare const DECISION_HALF_LIFE_DAYS = 90;
/**
 * Test-only helper. Tests that mutate `process.env.HIPPO_LOSS_AVERSION_RATIO`
 * MUST call this in BOTH `beforeEach` AND `afterEach`:
 *   - beforeEach: clear any stale cache from a previous test before setting
 *     the env var for this test.
 *   - afterEach: clear the cache so the next test (which may not set the env
 *     var) reads the clean default instead of this test's value.
 * See `tests/emotional-multipliers-j5.test.ts` for the canonical pattern.
 */
export declare function _resetLossAversionRatioCacheForTests(): void;
/**
 * Compute the reward factor from cumulative outcome counts.
 *
 *   reward_ratio  = (positive - negative) / (positive + negative + 1)
 *   reward_factor = 1 + 0.5 * reward_ratio
 *
 * Range: (0.5, 1.5). Neutral (no outcomes) returns 1.0.
 * Modulates effective half-life: memories with consistent positive outcomes
 * decay slower; consistent negative outcomes decay faster.
 */
export declare function calculateRewardFactor(entry: MemoryEntry): number;
/**
 * Options for decay basis.
 * - clock: wall-clock time (default pre-v0.15)
 * - session: decay by sleep cycle count (for intermittent agents)
 * - adaptive: auto-scale half-life by session frequency (default v0.15+)
 */
export interface DecayOptions {
    decayBasis?: 'clock' | 'session' | 'adaptive';
    /** Average interval between sleep cycles, in days. Used by 'adaptive' and 'session' modes. */
    avgSessionIntervalDays?: number;
    /** Total sleep cycles completed. Used by consolidation tracking. */
    sleepCount?: number;
}
/**
 * Calculate current strength at a given time.
 * strength(t) = base_strength * decay * retrieval_boost * emotional_multiplier
 *
 * Decay basis modes:
 * - clock: classic wall-clock decay (daysSince / halfLife)
 * - session: decay by sleep cycles instead of days (sessionsSince / halfLife)
 * - adaptive: wall-clock decay with half-life scaled by session frequency
 *
 * Pinned memories always return 1.0 (no decay).
 */
export declare function calculateStrength(entry: MemoryEntry, now?: Date, options?: DecayOptions): number;
/**
 * Derive half-life based on signals, as per PLAN.md table.
 */
export declare function deriveHalfLife(base: number, entry: Partial<MemoryEntry>): number;
/**
 * Apply outcome feedback to a memory entry.
 *
 * Increments outcome_positive or outcome_negative counters.
 * The reward factor in calculateStrength() uses these counts to
 * continuously modulate the effective half-life:
 *   reward_ratio  = (pos - neg) / (pos + neg + 1)
 *   reward_factor = 1 + 0.5 * reward_ratio    // range (0.5, 1.5)
 *   effective_hl  = half_life_days * reward_factor
 *
 * No fixed half-life delta. Decay rate adjusts proportionally to
 * cumulative reward signal, inspired by R-STDP in spiking networks.
 */
export declare function applyOutcome(entry: MemoryEntry, good: boolean): MemoryEntry;
/**
 * Generate a random memory ID using crypto.randomUUID().
 */
export declare function generateId(prefix?: string): string;
/**
 * Resolve the effective confidence for a memory entry.
 * If the entry has not been retrieved in 30+ days and is not 'verified',
 * returns 'stale'. Otherwise returns the stored confidence value.
 */
export declare function resolveConfidence(entry: MemoryEntry, now?: Date): ConfidenceLevel;
/**
 * Create a new memory entry with defaults.
 */
export declare function createMemory(content: string, options?: {
    layer?: Layer;
    tags?: string[];
    emotional_valence?: EmotionalValence;
    pinned?: boolean;
    schema_fit?: number;
    source?: string;
    confidence?: ConfidenceLevel;
    baseHalfLifeDays?: number;
    trace_outcome?: TraceOutcome;
    source_session_id?: string | null;
    valid_from?: string;
    extracted_from?: string;
    dag_level?: number;
    dag_parent_id?: string;
    kind?: MemoryKind;
    scope?: string | null;
    owner?: string | null;
    artifact_ref?: string | null;
    tenantId?: string;
}): MemoryEntry;
/**
 * Compute how well new content fits existing knowledge patterns.
 * Returns 0..1 where:
 *   >0.7 = high fit (consistent with existing knowledge, consolidates faster)
 *   0.3-0.7 = moderate fit
 *   <0.3 = novel (doesn't match existing patterns, decays faster if unused)
 *
 * Uses tag overlap (always available) weighted by how common each tag is.
 * Rare shared tags signal stronger schema fit than common ones.
 */
export declare function computeSchemaFit(content: string, tags: string[], existingEntries: MemoryEntry[]): number;
//# sourceMappingURL=memory.d.ts.map