import type { DatabaseSync } from "node:sqlite";
import type { ChunkKind, L3CycleResult } from "./types.js";
/**
 * Exponential-decay half-life (days) per chunk kind. Longer half-life =
 * slower forgetting. Used in stage 1.
 */
export declare const KIND_HALF_LIFE_DAYS: Record<ChunkKind, number>;
/**
 * Ranking multiplier per kind in stage 5 (promotion). Higher = prefers
 * kind when selecting top-N for a section.
 */
export declare const KIND_WEIGHT: Record<ChunkKind, number>;
/** Cosine-similarity threshold for stage 2 reinforcement. */
export declare const REINFORCE_SIMILARITY_THRESHOLD = 0.85;
/** Edge-hop propagation factor (stage 3). Conservative to avoid runaway feedback. */
export declare const PROPAGATION_FACTOR = 0.1;
/** Stage 6 pruning criteria. All must hold. */
export declare const PRUNE_MIN_IMPORTANCE = 0.2;
export declare const PRUNE_MIN_AGE_DAYS = 90;
/** Stage 5 caps so the visible L1 files don't balloon. */
export declare const SYMI_CORE_MAX_BULLETS_PER_SECTION = 15;
export declare const SYMI_BELIEFS_MAX = 40;
/** Stage 4 clustering defaults. */
export declare const CLUSTER_MUTUAL_THRESHOLD = 0.75;
export declare const CLUSTER_MIN_SIZE = 3;
export declare const CLUSTER_MIN_IMPORTANCE = 1;
/**
 * Minimum gap between autonomous cycles. Post-flush may fire many times
 * in rapid succession; this guard avoids back-to-back pipeline runs.
 */
export declare const DEFAULT_MIN_INTERVAL_MS: number;
export declare const META_LAST_L3_CYCLE_AT = "l3_last_cycle_at";
export declare const SYMI_CORE_PATH = "memory/symi-core.md";
export declare const SYMI_BELIEFS_PATH = "memory/symi-beliefs.md";
export type L3CycleParams = {
    db: DatabaseSync;
    workspaceDir: string;
    /**
     * Optional — when supplied, stage 4 runs. When omitted, stage 4 is
     * skipped and the cycle still delivers decay/reinforce/propagate/
     * promote/prune. Callers without a synthesis runner get a
     * degraded-but-useful cycle.
     */
    synthesize?: SynthesizeFn;
    /** Tunable overrides; all default to the constants above. */
    overrides?: {
        halfLifeDays?: Partial<Record<ChunkKind, number>>;
        kindWeight?: Partial<Record<ChunkKind, number>>;
        reinforceThreshold?: number;
        propagationFactor?: number;
        pruneMinImportance?: number;
        pruneMinAgeDays?: number;
        maxBulletsPerSection?: number;
        maxBeliefs?: number;
        clusterMutualThreshold?: number;
        clusterMinSize?: number;
        clusterMinImportance?: number;
    };
};
/**
 * Called by stage 4 for each cluster of highly-similar high-importance
 * observations. Implementation lives in `synthesis.ts` so consolidate.ts
 * stays free of agent-turn plumbing. Returning null skips the cluster
 * (e.g. if the synthesizer was uncertain).
 */
export type SynthesizeFn = (cluster: {
    sources: Array<{
        id: string;
        text: string;
        importance: number;
    }>;
}) => Promise<{
    text: string;
    kind: Exclude<ChunkKind, "observation">;
} | null>;
export type SynthesizedBelief = {
    text: string;
    kind: Exclude<ChunkKind, "observation">;
    confidence: number;
    sourceIds: string[];
};
/**
 * Apply exponential decay based on age since last access. Pinned chunks
 * are exempt. Kinds with longer half-lives decay slower.
 *
 * Formula: importance *= exp(-ln(2) / halfLifeDays * ageDays)
 */
export declare function stageDecay(params: {
    db: DatabaseSync;
    now?: number;
    halfLifeDays?: Partial<Record<ChunkKind, number>>;
}): {
    decayed: number;
};
/**
 * For chunks created since the previous cycle, find semantically similar
 * older chunks. Each hit bumps the older chunk's reinforcement_count and
 * boosts its importance by a diminishing-returns log factor.
 *
 * The new chunk itself is unchanged — it stays a fresh observation. Only
 * older chunks that "heard the same thing again" get strengthened. This
 * is how repeated themes compound into durable beliefs.
 */
export declare function stageReinforce(params: {
    db: DatabaseSync;
    sinceTs: number;
    threshold?: number;
}): {
    reinforced: number;
};
/**
 * One-hop edge propagation: each chunk's importance gains a fraction of
 * its neighbours' importance. Uses the existing `edges` table.
 *
 * Computed as a single SQL aggregate so we don't round-trip per-chunk.
 */
export declare function stagePropagate(params: {
    db: DatabaseSync;
    factor?: number;
}): {
    propagated: number;
};
export type ClusterCandidate = {
    members: Array<{
        id: string;
        text: string;
        importance: number;
        embedding: number[];
    }>;
};
/**
 * Find clusters of highly-similar high-importance observation chunks.
 * Each cluster is a connected component of the "cosine > mutualThreshold"
 * graph restricted to observations that have not yet been promoted.
 *
 * Clusters smaller than `minSize` are discarded.
 */
export declare function findSynthesisClusters(params: {
    db: DatabaseSync;
    mutualThreshold?: number;
    minSize?: number;
    minImportance?: number;
}): ClusterCandidate[];
/**
 * Regenerate `memory/symi-core.md` and `memory/symi-beliefs.md`.
 *
 * - symi-core.md is a full rewrite from top-ranked chunks, grouped by
 *   section. Hand edits are clobbered; that's deliberate — it's a
 *   projection of DB state.
 *
 * - symi-beliefs.md is a merge: existing beliefs parsed from the file,
 *   new beliefs from stage 4 added (dedupe by text hash), sorted by
 *   confidence, capped at SYMI_BELIEFS_MAX.
 *
 * Promoted chunks get marked with `promoted_to = <path>` so stage 6
 * knows not to prune them.
 */
export declare function stagePromote(params: {
    db: DatabaseSync;
    workspaceDir: string;
    synthesizedBeliefs?: SynthesizedBelief[];
    maxBulletsPerSection?: number;
    maxBeliefs?: number;
    kindWeight?: Partial<Record<ChunkKind, number>>;
    now?: number;
}): Promise<{
    promoted: number;
    paths: {
        symiCore: string;
        symiBeliefs: string;
    };
}>;
/**
 * Hard-delete chunks that meet ALL criteria. Conservative on purpose —
 * L1 is the source of truth, so next sync re-ingests anything wrongly
 * pruned. Cascades across the chunk's companion vec/fts rows.
 */
export declare function stagePrune(params: {
    db: DatabaseSync;
    vectorTable?: string;
    ftsTable?: string;
    now?: number;
    minImportance?: number;
    minAgeDays?: number;
}): {
    pruned: number;
};
export declare function runL3Cycle(params: L3CycleParams): Promise<L3CycleResult>;
export declare function runL3CycleIfDue(params: L3CycleParams & {
    minIntervalMs?: number;
}): Promise<L3CycleResult>;
