/**
 * STDP (Spike-Timing-Dependent Plasticity) for CLEO BRAIN.
 *
 * Implements a biologically-inspired Hebbian learning rule that modulates edge
 * weights based on the *temporal order* of memory retrievals within a session
 * window, not just co-occurrence frequency.
 *
 * ## Neuroscience basis
 *
 * Classical STDP: if neuron A fires before neuron B by Δt milliseconds, the
 * synapse A→B is potentiated (LTP); if A fires after B, it is depressed (LTD).
 * The magnitude of the change decays exponentially with |Δt|.
 *
 * ## Mapping to CLEO memory
 *
 * - Each entry retrieved from brain.db is a "spike".
 * - Retrievals within the same session and within `sessionWindowMs` of each
 *   other are treated as temporally related spikes.
 * - If entry A was retrieved BEFORE entry B by Δt ms:
 *     Δw = A_pre  × exp(−Δt / τ_pre)   → potentiation (LTP, positive Δw)
 * - If entry A was retrieved AFTER entry B by Δt ms:
 *     Δw = −A_post × exp(−Δt / τ_post)  → depression  (LTD, negative Δw)
 * - Weights are clamped to [0.0, 1.0].
 * - All events are logged to `brain_plasticity_events` for observability.
 *
 * ## Parameters (biologically reasonable defaults)
 *
 * | Symbol  | Value  | Meaning                                          |
 * |---------|--------|--------------------------------------------------|
 * | τ_pre   | 20 s   | Time constant for pre→post potentiation          |
 * | τ_post  | 20 s   | Time constant for post→pre depression            |
 * | A_pre   | 0.05   | Peak potentiation amplitude                      |
 * | A_post  | 0.06   | Peak depression amplitude (asymmetric, per STDP) |
 *
 * The asymmetry A_post > A_pre models the biological fact that LTD is slightly
 * stronger than LTP, preventing runaway weight growth.
 *
 * ## Relation to Hebbian co-retrieval
 *
 * Hebbian (`strengthenCoRetrievedEdges` in brain-lifecycle.ts) uses the
 * `co_retrieved` edge type and does NOT track order; it fires on pairs that
 * co-occur ≥ 3× regardless of timing. STDP is a *second plasticity pass* that
 * runs after Hebbian and refines existing `co_retrieved` edges using order data.
 *
 * If no `co_retrieved` edge exists yet between a pair, STDP inserts one with the
 * initial STDP-derived weight (potentiation pairs only — LTD does not create
 * new edges, only weakens existing ones).
 *
 * ## Two-Window Architecture (T679 BUG-1 fix, T688 expansion)
 *
 * Prior code used `sessionWindowMs=5min` as BOTH the SQL lookback cutoff AND the
 * spike-pair Δt gate, causing all live rows (>5min old) to produce zero plasticity
 * events. This version separates the two concerns:
 *
 * | Parameter         | Default    | Purpose                                  |
 * |-------------------|------------|------------------------------------------|
 * | `lookbackDays`    | 30 days    | SQL cutoff for fetching retrieval rows   |
 * | `pairingWindowMs` | 24 h       | Max Δt between two spikes for pairing    |
 *
 * T688: `pairingWindowMs` raised to 24 h — cross-session pairs now eligible.
 * Session boundary is NOT a hard cutoff; τ tier determines decay magnitude.
 *
 * ## Tiered τ (T689)
 *
 * `computeTau(deltaT)` selects the decay time constant based on Δt:
 *
 * | Gap class     | Δt range       | τ       |
 * |---------------|----------------|---------|
 * | Intra-batch   | 0 — 30 s       | 20 s    |
 * | Intra-session | 30 s — 2 h     | 30 min  |
 * | Cross-session | 2 h — 24 h     | 12 h    |
 *
 * ## R-STDP reward modulation (T692)
 *
 * `reward_signal r` (from Step 9a backfill) gates Δw per spike:
 *   Δw_ltp_effective = clamp(Δw_ltp × (1+r), 0, 2×A_pre)
 *   Δw_ltd_effective = clamp(Δw_ltd × (1-r), -2×A_post, 0)
 * null reward → no modulation (r treated as 0).
 *
 * ## Novelty boost (T691)
 *
 * On INSERT (first co-retrieval), initial_weight = clamp(Δw × 1.5, 0, A_pre×1.5).
 * UPDATE path uses un-boosted Δw.
 *
 * @task T626
 * @task T679
 * @task T688
 * @task T689
 * @task T691
 * @task T692
 * @epic T673
 * @see packages/core/src/memory/brain-lifecycle.ts#strengthenCoRetrievedEdges
 * @see docs/specs/stdp-wire-up-spec.md §3.2 Two-Window Architecture
 */
/**
 * Result returned by `backfillRewardSignals`.
 *
 * @task T681
 * @epic T673
 */
export interface RewardBackfillResult {
    /** Number of brain_retrieval_log rows updated with a reward_signal. */
    rowsLabeled: number;
    /** Number of rows skipped (already labeled, backfill session, or no task match). */
    rowsSkipped: number;
}
/**
 * Options for `applyStdpPlasticity`.
 *
 * ### Migration note — legacy number signature deprecated (T679)
 *
 * The old single-parameter signature `applyStdpPlasticity(root, sessionWindowMs)`
 * used the same value for both SQL lookback cutoff and spike-pair Δt gate.
 * All 38 live retrieval rows were older than 5 min, so zero events ever fired.
 *
 * Pass `lookbackDays` (how far back to fetch rows) and `pairingWindowMs`
 * (max Δt between two spikes for pair formation) as separate parameters.
 */
export interface StdpPlasticityOptions {
    /**
     * SQL lookback window: only retrieve log rows from the last N days.
     * Default: 30. A 30-day window captures all meaningful retrieval history
     * without unbounded growth.
     */
    lookbackDays?: number;
    /**
     * Maximum Δt (ms) between two spikes for them to form a STDP pair.
     * T688 default: 24 h (86,400,000 ms) — cross-session pairs are eligible.
     * Tiered τ (T689) applies different decay constants based on session
     * relationship and Δt magnitude, so cross-session pairs still get
     * significantly smaller Δw than intra-batch pairs.
     */
    pairingWindowMs?: number;
}
/**
 * Select the decay time constant τ based on spike-pair temporal gap.
 *
 * Three tiers (per spec §3.3):
 * - τ_near = 20 s   — Δt ≤ 30 s  (intra-batch, classical STDP window)
 * - τ_session = 30 min — 30 s < Δt ≤ 2 h (intra-session, working memory)
 * - τ_episodic = 12 h — Δt > 2 h  (cross-session, episodic reconsolidation)
 *
 * @param deltaT - Time gap between spikes in milliseconds (non-negative).
 * @returns τ in milliseconds for use in exp(-Δt / τ).
 *
 * @task T689
 */
export declare function computeTau(deltaT: number): number;
/** Result returned by `applyStdpPlasticity`. */
export interface StdpPlasticityResult {
    /** Number of LTP (potentiation) events applied. */
    ltpEvents: number;
    /** Number of LTD (depression) events applied. */
    ltdEvents: number;
    /** Number of new edges inserted (LTP on pairs without an existing edge). */
    edgesCreated: number;
    /** Number of retrieval pairs examined. */
    pairsExamined: number;
    /**
     * Number of pairs where reward_signal was non-null and modulated Δw.
     * Incremented for both LTP and LTD events that had a non-null reward.
     *
     * @task T692
     */
    rewardModulatedEvents: number;
}
/** Summary row from `getPlasticityStats`. */
export interface PlasticityStatsSummary {
    /** Total number of plasticity events ever recorded. */
    totalEvents: number;
    /** Count of LTP events. */
    ltpCount: number;
    /** Count of LTD events. */
    ltdCount: number;
    /** Net weight delta summed across all events (positive = net strengthening). */
    netDeltaW: number;
    /** Most recent event timestamp (ISO 8601), or null if no events. */
    lastEventAt: string | null;
    /** Recent events (up to `limit`, newest first). */
    recentEvents: RecentPlasticityEvent[];
}
/** A single recent plasticity event for display. */
export interface RecentPlasticityEvent {
    /** Auto-increment event ID. */
    id: number;
    /** Source node identifier. */
    sourceNode: string;
    /** Target node identifier. */
    targetNode: string;
    /** Signed weight delta. */
    deltaW: number;
    /** 'ltp' or 'ltd'. */
    kind: 'ltp' | 'ltd';
    /** ISO 8601 timestamp. */
    timestamp: string;
    /** Session ID, if available. */
    sessionId: string | null;
}
/**
 * T714: Check whether Step 9b (STDP plasticity) should run based on retrieval volume.
 *
 * Per spec §4.2, skip plasticity processing if fewer than `minRetrievalsForPlasticity`
 * new retrieval rows exist since the last `brain_plasticity_events` timestamp.
 * This prevents wasted compute on early-session edge cases where no meaningful pairs exist.
 *
 * @param projectRoot - Project root for brain.db resolution
 * @param sessionId - Session ID to check (null = all sessions)
 * @param minRetrievalsForPlasticity - Minimum row count required. Default: 2.
 * @returns True if plasticity should run; false if gate blocks it.
 */
export declare function shouldRunPlasticity(projectRoot: string, sessionId?: string | null, minRetrievalsForPlasticity?: number): Promise<boolean>;
/**
 * Apply Spike-Timing-Dependent Plasticity to brain_page_edges.
 *
 * Reads `brain_retrieval_log` for rows within the past `lookbackDays` days
 * (default 30), reconstructs the temporal spike sequence, and applies the
 * STDP rule to every ordered pair within `pairingWindowMs` (default 24 h).
 *
 * All weight changes are logged to `brain_plasticity_events` (with
 * `session_id`, `retrieval_log_id`, `weight_before`, `weight_after`,
 * `delta_t_ms`) and to `brain_weight_history` for the full audit trail.
 *
 * ### T679 fixes (root cause: BUG-1 from stdp-wire-up-spec.md §1.4)
 *
 * - Separated `lookbackDays` (SQL fetch window, default 30d) from
 *   `pairingWindowMs` (spike-pair Δt gate, default 5min). Previously both
 *   used `sessionWindowMs=5min`, causing all live rows (>5min old) to produce
 *   zero events.
 * - Writer now populates `session_id` + `retrieval_log_id` + `weight_before` /
 *   `weight_after` on `brain_plasticity_events` INSERT.
 * - Writer now inserts into `brain_weight_history` per weight delta.
 * - Fixed bug where `prepareUpdateEdge.run()` was missing 4 of 9 SQL params.
 *
 * ### Backward compatibility
 *
 * The legacy `applyStdpPlasticity(root, number)` signature is still accepted.
 * The number is mapped to `pairingWindowMs`; `lookbackDays` stays at 30d.
 * A deprecation warning is emitted to steer callers to `StdpPlasticityOptions`.
 *
 * @param projectRoot - Project root directory for brain.db resolution
 * @param options - `StdpPlasticityOptions` or a legacy number (deprecated `sessionWindowMs`).
 * @returns Counts of LTP/LTD events applied and edges created/updated.
 */
export declare function applyStdpPlasticity(projectRoot: string, options?: StdpPlasticityOptions | number): Promise<StdpPlasticityResult>;
/**
 * Retrieve a summary of recent STDP plasticity events from `brain_plasticity_events`.
 *
 * Used by `cleo brain plasticity stats`.
 *
 * @param projectRoot - Project root directory for brain.db resolution
 * @param limit - Maximum number of recent events to include. Defaults to 20.
 * @returns Aggregated plasticity statistics and the most recent events.
 */
export declare function getPlasticityStats(projectRoot: string, limit?: number): Promise<PlasticityStatsSummary>;
/**
 * Backfill reward_signal values on brain_retrieval_log rows for a session.
 *
 * Step 9a of the `runConsolidation` pipeline — runs BEFORE `applyStdpPlasticity`
 * (Step 9b) so reward signals are present when STDP reads them.
 *
 * ## Signal derivation
 *
 * Queries tasks.db for tasks attributed to `sessionId` within `lookbackDays`.
 * Maps task outcomes to reward scalars:
 *
 * | Task state | Reward |
 * |-----------|--------|
 * | `status='done'`, `verification.passed=true` | +1.0 (verified correct) |
 * | `status='done'`, verification not passed | +0.5 (completed, unverified) |
 * | `status='cancelled'` | -0.5 (cancelled) |
 *
 * All brain_retrieval_log rows for the session receive the derived scalar as
 * a session-level reward (the entire session's retrieval pattern is rated by
 * the session's overall task outcome). If multiple tasks exist in the session,
 * the MAXIMUM reward takes precedence (positive outcome wins).
 *
 * ## Skipped sessions
 *
 * Sessions with `session_id LIKE 'ses_backfill_%'` are synthetic (date-bucketed
 * historical rows per M1). These have no real task correlation and MUST be skipped.
 *
 * ## Idempotency
 *
 * Already-labeled rows (reward_signal IS NOT NULL) are not overwritten.
 * Running twice on the same session is safe.
 *
 * ## Transaction pattern
 *
 * Two separate SQLite connections (no ATTACH): reads tasks.db → computes reward
 * map → writes brain.db in separate transactions. Matches `cross-db-cleanup.ts`.
 *
 * @param projectRoot - Project root directory for database resolution
 * @param sessionId - The session ID to backfill. Pass null/undefined for no-op.
 * @param lookbackDays - Days of tasks.db history to scan (default 30)
 * @returns Counts of rows labeled and skipped
 *
 * @task T681
 * @epic T673
 */
export declare function backfillRewardSignals(projectRoot: string, sessionId: string | null | undefined, lookbackDays?: number): Promise<RewardBackfillResult>;
/**
 * Options for `applyHomeostaticDecay`.
 *
 * @task T690
 * @epic T673
 */
export interface HomeostaticDecayOptions {
    /**
     * Fractional weight loss per day for idle edges.
     * Default: 0.02 (2%/day → weight halves in ~35 days).
     * Spec §3.9 default: decay_rate=0.02.
     */
    decayRatePerDay?: number;
    /**
     * Days of idle time before decay begins.
     * Edges reinforced more recently than this are left untouched.
     * Default: 7 days — keeps weekly-session edges alive.
     */
    gracePeriodDays?: number;
    /**
     * Edges whose post-decay weight falls below this threshold are pruned (deleted).
     * Default: 0.05 (5%) — no meaningful signal below this floor.
     */
    pruneThreshold?: number;
}
/**
 * Result returned by `applyHomeostaticDecay`.
 *
 * @task T690
 * @epic T673
 */
export interface HomeostaticDecayResult {
    /** Number of edges whose weight was reduced by the decay pass (still above pruneThreshold). */
    edgesDecayed: number;
    /** Number of edges deleted because their post-decay weight fell below pruneThreshold. */
    edgesPruned: number;
}
/**
 * Apply homeostatic weight decay to `hebbian` and `stdp` brain edges (Step 9c).
 *
 * Runs after `applyStdpPlasticity` (Step 9b) in the consolidation pipeline.
 * For each `co_retrieved` edge with `plasticity_class IN ('hebbian', 'stdp')` and
 * `last_reinforced_at` older than `gracePeriodDays`, applies:
 *
 * ```
 * new_weight = current_weight × (1 - decayRatePerDay) ^ days_idle
 * ```
 *
 * where `days_idle = (now − last_reinforced_at) − gracePeriodDays`.
 *
 * If `new_weight < pruneThreshold`, the edge is **deleted** and a
 * `brain_weight_history` row with `event_kind='prune'` is written.
 * If `new_weight >= pruneThreshold`, the weight is updated **without**
 * writing to `brain_weight_history` (routine decay is not logged per
 * spec §1 decision #11).
 *
 * **Protected edge classes** (never touched):
 * - `plasticity_class = 'static'` — structural edges
 * - `plasticity_class = 'external'` — externally owned edges
 * - Edges with `last_reinforced_at IS NULL` — never reinforced, skip decay
 *
 * @param projectRoot - Project root directory for brain.db resolution
 * @param options - Decay configuration (see `HomeostaticDecayOptions`)
 * @returns Counts of edges decayed and pruned
 *
 * @task T690
 * @epic T673
 * @see docs/specs/stdp-wire-up-spec.md §3.9
 */
export declare function applyHomeostaticDecay(projectRoot: string, options?: HomeostaticDecayOptions): Promise<HomeostaticDecayResult>;
//# sourceMappingURL=brain-stdp.d.ts.map