import { VersioningConfig } from './page-versioning.js';
import { ConsolidationOperator } from './consolidation-operator.js';
import { PluginConfig, MemoryCategory, ImportanceScore, MemoryLink, MemoryFrontmatter, MemoryStatus, MemoryFile, EntityStructuredSection, BufferState, MetaState, MemoryActionEvent, MemoryLifecycleEvent, BufferSurpriseEvent, BehaviorSignalEvent, CompressionGuidelineOptimizerState, ContinuityIncidentOpenInput, ContinuityIncidentRecord, ContinuityIncidentCloseInput, ContinuityImprovementLoop, ContinuityLoopUpsertInput, ContinuityLoopReviewInput, FileHygieneConfig, EntityRelationship, EntityActivityEntry, EntityFile, AccessTrackingEntry, MemoryProjectionCurrentState, MemorySummary, TopicScore } from './types.js';
import { P as ProjectedMemoryBrowseOptions, a as ProjectedMemoryBrowsePage, b as readProjectedGovernanceRecord } from './memory-projection-store-D3vBHS4J.js';
import 'better-sqlite3';

interface ReextractJobRequest {
    memoryId: string;
    model: string;
    requestedAt: string;
    source: "cli-migrate";
}
interface MemoryLifecycleEventWriteOptions {
    at?: Date;
    actor?: string;
    reasonCode?: string;
    ruleVersion?: string;
    relatedMemoryIds?: string[];
    correlationId?: string;
}
/**
 * Normalize an entity name to a canonical form.
 * Strips non-alphanumeric chars, collapses hyphens, removes type prefix duplication.
 * e.g. "My Project" → "my-project"
 *
 * Checks user-defined aliases (from config/aliases.json) first, then built-in aliases.
 */
declare function normalizeEntityName(raw: string, type: string): string;
/**
 * Content-hash dedup index for facts.
 * Normalizes content (lowercase, strip punctuation, collapse whitespace),
 * computes SHA-256, and stores hashes in a line-delimited file.
 * Prevents writing semantically identical facts.
 */
declare class ContentHashIndex {
    private hashes;
    private dirty;
    private readonly filePath;
    private readonly secureStoreKeyProvider;
    private readonly secureStoreWriteKeyProvider;
    private readonly memoryDir;
    constructor(stateDir: string, secureStoreKeyProvider?: () => Buffer | null, secureStoreWriteKeyProvider?: () => Buffer | null, memoryDir?: string);
    /** Load existing hashes from disk. Safe to call multiple times. */
    load(): Promise<void>;
    /** Check if content already exists in the index. */
    has(content: string): boolean;
    /** Add content hash to the index. */
    add(content: string): void;
    get size(): number;
    /** Persist index to disk if changed. */
    save(): Promise<void>;
    /** Remove a hash from the index (used when archiving/deleting). */
    remove(content: string): void;
    /**
     * Remove a pre-computed SHA-256 hash directly from the index without
     * re-hashing.  Use this when the caller already holds the stored hash
     * (e.g. `memory.frontmatter.contentHash`) to avoid the double-hash bug
     * where `remove(hash)` would compute `hash(hash)` and never match the
     * entry.
     */
    removeByHash(hash: string): void;
    /**
     * Add a pre-computed SHA-256 hash directly to the index without re-hashing.
     * Use this when the caller already holds the stored hash
     * (e.g. `memory.frontmatter.contentHash`) so that the index records the raw
     * content hash rather than re-hashing the citation-annotated body.
     *
     * @internal Only called from `StorageManager.ensureFactHashIndexAuthoritative`.
     * Not part of the public API — prefer `add(content)` for external callers.
     */
    addByHash(hash: string): void;
    /** Normalize content and compute SHA-256 hash. */
    static normalizeContent(content: string): string;
    /** Normalize content and compute SHA-256 hash. */
    static computeHash(content: string): string;
}
/**
 * Render a structured-attributes map into a stable, canonical string fragment
 * suitable for appending to enriched memory content before hashing.
 *
 * Normalization rules:
 *   - Keys are trimmed and lowercased (values are trimmed but preserve case)
 *   - Key-value pairs are sorted alphabetically by normalized key
 *   - Pairs are joined with "; " and rendered as "key: value"
 *
 * Using this helper at BOTH the write path (enrichedContent) and the
 * dedup-lookup path (dedupContent) guarantees identical output regardless of
 * the insertion order or casing used by the caller.
 *
 * @example
 *   normalizeAttributePairs({ foo: "bar", BAZ: "qux" })
 *   // → "baz: qux; foo: bar"
 */
declare function normalizeAttributePairs(pairs: Record<string, string>): string;
declare function compareEntityTimestamps(left?: string, right?: string): number;
declare function fingerprintEntityStructuredFacts(entity: Pick<EntityFile, "structuredSections">): string | undefined;
declare function isEntitySynthesisStale(entity: EntityFile): boolean;
/**
 * Parse an entity markdown file into a structured EntityFile.
 * Backward compatible: old files without new sections get empty arrays.
 */
declare function parseEntityFile(content: string, entitySchemas?: PluginConfig["entitySchemas"]): EntityFile;
/**
 * Serialize an EntityFile back to markdown.
 * Writes the compiled-truth + timeline format while remaining parse-compatible
 * with the legacy in-memory `summary` and `facts` fields.
 */
declare function serializeEntityFile(entity: EntityFile, entitySchemas?: PluginConfig["entitySchemas"]): string;
declare class StorageManager {
    private readonly baseDir;
    private readonly entitySchemas?;
    private knowledgeIndexCache;
    private static readonly KNOWLEDGE_INDEX_CACHE_TTL_MS;
    private artifactIndexCache;
    private static readonly ARTIFACT_INDEX_CACHE_TTL_MS;
    private static readonly artifactWriteVersionByDir;
    private static readonly memoryStatusVersionByDir;
    private static readonly secureStoreEntityCacheKeyIds;
    private static nextSecureStoreEntityCacheKeyId;
    private static readonly coldWriteVersionByDir;
    private static readonly allMemoriesInFlight;
    private static readonly COLD_SCAN_CACHE_TTL_MS;
    private static readonly coldMemoriesCache;
    private static readonly QUESTIONS_CACHE_TTL_MS;
    private static readonly questionsCache;
    private factHashIndex;
    private factHashIndexLoadPromise;
    private factHashIndexAuthoritative;
    private factHashIndexAuthoritativePromise;
    private readonly secureAppendChains;
    /** Optional: set by the orchestrator after construction to enable template-aware citation stripping during legacy hash rebuild. */
    citationTemplate: string;
    /** Page-versioning configuration.  Set by the orchestrator after construction. */
    private _versioningConfig;
    /** Set the page-versioning configuration.  When `enabled` is false (default), all versioning calls are no-ops. */
    setVersioningConfig(config: VersioningConfig): void;
    /**
     * At-rest encryption key (issue #690 PR 3/4).
     *
     * When non-null, every memory file read is decrypted and every write
     * is encrypted using the secure-fs layer.  When null, the storage
     * layer operates in plain-text mode (legacy/unencrypted store).
     *
     * Set by the orchestrator after init/unlock; cleared on lock.
     * The key buffer is NEVER logged or serialized.
     */
    private _secureStoreKey;
    /**
     * When true (and `_secureStoreKey` is non-null), new writes are
     * encrypted.  Set to false to pause encryption of new writes while
     * still decrypting existing files.
     */
    private _secureStoreEncryptOnWrite;
    /**
     * When true, the secure-store is configured as required — writes
     * MUST be encrypted and a locked store MUST reject writes rather
     * than silently falling back to plaintext.  Set by the orchestrator
     * from `config.secureStoreEnabled`.
     */
    private _secureStoreRequired;
    /**
     * Set or clear the at-rest encryption key.
     *
     * Pass a 32-byte Buffer to enable encryption; pass null to clear
     * (lock) the store.  The caller is responsible for key lifecycle —
     * this method does not zero the buffer on replacement; the keyring
     * module (`keyring.ts`) owns zeroization.
     */
    setSecureStoreKey(key: Buffer | null, encryptOnWrite?: boolean): void;
    private getEntityCacheSecureStoreKey;
    /**
     * Mark the secure-store as required for this storage instance.
     * When required and locked, writes throw SecureStoreLockedError
     * rather than silently writing plaintext.
     */
    setSecureStoreRequired(required: boolean): void;
    /** Return true iff the secure-store key is currently set (store is unlocked). */
    isSecureStoreUnlocked(): boolean;
    /**
     * Resolve the effective write key.
     *
     * - If `_secureStoreEncryptOnWrite` is false: returns null (plain write).
     * - If `_secureStoreEncryptOnWrite` is true AND key is set: returns key.
     * - If `_secureStoreEncryptOnWrite` is true AND key is null AND
     *   `_secureStoreRequired` is true: throws SecureStoreLockedError so the
     *   write fails loudly rather than silently writing plaintext (P1 finding
     *   from Cursor review of PR #767).
     * - If `_secureStoreEncryptOnWrite` is true AND key is null AND
     *   `_secureStoreRequired` is false: returns null (unencrypted store).
     */
    private resolveWriteKey;
    /**
     * Snapshot the current content of a page before overwriting.
     * No-op when versioning is disabled or the file does not yet exist.
     */
    private snapshotBeforeWrite;
    /**
     * Consolidation provenance helper (issue #561 PR 2).
     *
     * Captures the current on-disk content of a source memory as a
     * page-version snapshot so the downstream consolidated write can record a
     * `derived_from` pointer that actually resolves.  Returns the
     * `"<relative-path>:<versionId>"` entry expected by the `derived_from`
     * frontmatter field.
     *
     * Returns `null` when versioning is disabled (snapshots would not be
     * created), when the file does not exist (nothing to snapshot), or when
     * the snapshot write itself fails (best-effort — callers skip the entry
     * rather than block the consolidation).
     */
    snapshotForProvenance(filePath: string): Promise<string | null>;
    constructor(baseDir: string, entitySchemas?: PluginConfig["entitySchemas"]);
    /** The root directory of this storage instance. */
    get dir(): string;
    private identityFilePath;
    private versionFilePath;
    private bumpSharedVersion;
    private readSharedVersion;
    private bumpMemoryStatusVersion;
    getMemoryStatusVersion(): number;
    private bumpArtifactWriteVersion;
    private getArtifactWriteVersion;
    private get factsDir();
    private get correctionsDir();
    private get proceduresDir();
    private get reasoningTracesDir();
    private get entitiesDir();
    private readStorageSecureFile;
    private writeStorageSecureFile;
    createContentHashIndex(): ContentHashIndex;
    private appendStorageSecureFile;
    private appendStorageSecureFileUnlocked;
    private get stateDir();
    private get entitySynthesisQueuePath();
    private get factHashIndexReadyPath();
    private getFactHashIndex;
    private ensureFactHashIndexAuthoritative;
    private get questionsDir();
    private get artifactsDir();
    private get identityDir();
    private get identityAnchorPath();
    private get identityIncidentsDir();
    private get identityAuditsWeeklyDir();
    private get identityAuditsMonthlyDir();
    private get identityImprovementLoopsPath();
    private get identityReflectionsPath();
    private get profilePath();
    private get memoryActionsPath();
    private get memoryLifecycleLedgerPath();
    private get compressionGuidelinesPath();
    private get compressionGuidelineDraftPath();
    private get compressionGuidelineStatePath();
    private get compressionGuidelineDraftStatePath();
    private get behaviorSignalsPath();
    /**
     * Buffer surprise telemetry ledger (issue #563 PR 3).
     *
     * Append-only JSONL of per-turn `BUFFER_SURPRISE` events emitted by
     * `SmartBuffer` when `bufferSurpriseTriggerEnabled` is on. Each row
     * captures the score, the threshold in force at the time, whether the
     * turn caused an extract_now upgrade, and the buffer size. Kept in
     * `state/` alongside the other append-only ledgers so cleanup and
     * governance sweeps can treat it uniformly.
     */
    private get bufferSurpriseLedgerPath();
    /**
     * Load user-defined entity aliases from config/aliases.json in the memory store.
     * File format: { "variant": "canonical", "variant2": "canonical", ... }
     * Call this once at startup (e.g. from orchestrator.initialize()).
     */
    loadAliases(): Promise<void>;
    ensureDirectories(): Promise<void>;
    writeMemory(category: MemoryCategory, content: string, options?: {
        actor?: string;
        confidence?: number;
        tags?: string[];
        entityRef?: string;
        source?: string;
        supersedes?: string;
        lineage?: string[];
        importance?: ImportanceScore;
        links?: MemoryLink[];
        intentGoal?: string;
        intentActionType?: string;
        intentEntityTypes?: string[];
        artifactType?: MemoryFrontmatter["artifactType"];
        sourceMemoryId?: string;
        sourceTurnId?: string;
        memoryKind?: MemoryFrontmatter["memoryKind"];
        expiresAt?: string;
        structuredAttributes?: Record<string, string>;
        /**
         * When provided, this string is used as the source for the fact-content
         * dedup hash index instead of the persisted body (`content`).
         *
         * Use this when the persisted body differs from the canonical fact text
         * — for example when `content` is a citation-annotated variant of a raw
         * fact. Passing the raw fact as `contentHashSource` ensures that
         * `hasFactContentHash(rawFact)` returns `true` after the write, so
         * subsequent extractions of the same logical fact are correctly deduped
         * even when their citation timestamp differs.
         */
        contentHashSource?: string;
        status?: MemoryStatus;
        /**
         * Consolidation provenance (issue #561 PR 2).  When the caller is a
         * consolidation / supersession / dedup-merge path, these fields wire
         * the page-version snapshots the new memory was derived from and the
         * operator that produced it.  Persisted onto frontmatter as
         * `derived_from` + `derived_via`; validated at serialize time.
         */
        derivedFrom?: string[];
        derivedVia?: ConsolidationOperator;
    }): Promise<string>;
    hasFactContentHash(content: string): Promise<boolean>;
    private factContentHashForRemoval;
    removeFactContentHashesForMemories(memories: MemoryFile[]): Promise<void>;
    isFactContentHashAuthoritative(): Promise<boolean>;
    writeArtifact(quote: string, options?: {
        actor?: string;
        tags?: string[];
        confidence?: number;
        artifactType?: MemoryFrontmatter["artifactType"];
        sourceMemoryId?: string;
        sourceTurnId?: string;
        intentGoal?: string;
        intentActionType?: string;
        intentEntityTypes?: string[];
    }): Promise<string>;
    private readAllArtifactsCached;
    searchArtifacts(query: string, maxResults: number): Promise<MemoryFile[]>;
    writeEntity(name: string, type: string, facts: string[], options?: {
        timestamp?: string;
        source?: string;
        sessionKey?: string;
        principal?: string;
        structuredSections?: EntityStructuredSection[];
    }): Promise<string>;
    readProfile(): Promise<string>;
    writeProfile(content: string): Promise<void>;
    /**
     * Normalize a string for fuzzy profile dedup: lowercase, strip punctuation, collapse whitespace.
     */
    private static normalizeForDedup;
    /**
     * Check if a new bullet is a fuzzy duplicate of any existing bullet.
     * Returns true if the new bullet should be skipped.
     */
    private static isFuzzyDuplicate;
    appendToProfile(updates: string[]): Promise<void>;
    /** Check if profile.md exceeds the max line cap and needs LLM consolidation */
    profileNeedsConsolidation(triggerLines?: number): Promise<boolean>;
    readAllMemories(): Promise<MemoryFile[]>;
    /** Invalidate the readAllMemories() cache after writes that add/remove memories. */
    /** Public cache invalidation for callers that need authoritative disk reads
     *  (e.g. projection verify/rebuild). */
    invalidateAllMemoriesCacheForDir(): void;
    /** Invalidate only the cache layers affected by direct tier file deletes. */
    invalidateMemoryCachesForTiers(tiers: Iterable<"hot" | "cold" | "archive">): void;
    /** Clear ALL static caches. Use in tests that write files directly
     *  (bypassing StorageManager.writeMemory) to avoid stale reads. */
    static clearAllStaticCaches(): void;
    /** Cancel any in-flight concurrent read so the next readAllMemories()
     *  starts a fresh disk scan and sees the just-written data.
     *
     *  Finding UvBq (PR #402 round-11): this method intentionally does NOT
     *  invalidate the cold-scan cache.  Ordinary hot-tier writes (writeMemory)
     *  do not change cold-tier content, so evicting the cold cache on every hot
     *  write was defeating the burst-dedup optimisation — the cold cache was
     *  cleared before applyTemporalSupersession ran, causing a full cold-tree
     *  disk scan on every write in a burst.  Cold cache invalidation is handled
     *  exclusively by invalidateColdMemoriesCache(), which is called only when
     *  cold content actually changes (hot→cold demotions, writeMemoryFileAtomic
     *  inside cold/, archiveMemory, etc.). */
    private invalidateAllMemoriesCache;
    /**
     * Invalidate the cold-scan cache for this storage root and bump the
     * on-disk cold-version sentinel so that other processes (gateway, CLI) see
     * the change immediately on their next readAllColdMemories() call.
     *
     * Must be called whenever a memory is written INTO the cold tier — hot→cold
     * demotion, atomic writes inside cold/, archiving a cold memory, etc.
     * NOT called on ordinary hot-tier writes (those don't change cold contents).
     *
     * Finding UvUy (PR #402 round-11): bumping the sentinel here makes the
     * per-process in-memory cache safe across process boundaries.
     */
    private invalidateColdMemoriesCache;
    /** Return the current cold-write version counter for this storage root.
     *  Reads the on-disk sentinel (state/cold-write.log) so it reflects writes
     *  made by other processes. */
    private readColdWriteVersion;
    /** Bump the on-disk cold-write version sentinel and update the in-process
     *  fallback map.  Called by invalidateColdMemoriesCache(). */
    private bumpColdWriteVersion;
    private normalizeMemoryReadBatchSize;
    private collectActiveMemoryPaths;
    private readParsedMemoriesFromPaths;
    private readWindowUpdatedMs;
    private filterWindowPathsByUpdatedAfter;
    private orderWindowPaths;
    private readWindowBoundedBatch;
    readMemoriesWindow(options?: {
        maxMemories?: number;
        batchSize?: number;
        updatedAfter?: Date;
    }): Promise<{
        memories: MemoryFile[];
        filePaths: string[];
    }>;
    private _readAllMemoriesFromDisk;
    /**
     * Read all memories from the cold tier by scanning the entire cold/ root
     * tree.  Previously this only scanned cold/facts/ and cold/corrections/, but
     * structuredAttributes can appear on any MemoryCategory (preference, decision,
     * entity, etc.).  Although buildTierMemoryPath currently routes all
     * non-correction, non-artifact memories to cold/facts/, scanning the full
     * coldRoot ensures correctness if that routing ever changes and guards against
     * files placed in unexpected subdirectories during manual operations or future
     * refactors.
     *
     * Broadened in PR #402 round-6 (Finding UTsP): scanning only facts/ and
     * corrections/ was a narrower-than-necessary subset of the cold directory
     * tree.  Correctness trumps the minor performance difference — cold scans
     * already happen at most once per supersession write.
     *
     * Used by applyTemporalSupersession so that memories already demoted to
     * cold/ can still be marked superseded when a newer hot fact arrives.
     *
     * Cached with a TTL (Finding UOGi, PR #402 round-6): back-to-back
     * structured-attribute writes in the same burst reuse the cached result
     * instead of re-scanning the cold tree on every call.  The cache is
     * invalidated whenever a write calls invalidateAllMemoriesCache() (which
     * covers any hot→cold demotion that changes cold-tier contents) and
     * expires after COLD_SCAN_CACHE_TTL_MS as a safety net.
     */
    readAllColdMemories(): Promise<MemoryFile[]>;
    /**
     * Read archived memory markdown files under archive/.
     * Used by long-term recall fallback when hot recall has no hits.
     */
    readArchivedMemories(): Promise<MemoryFile[]>;
    /** Read a single memory file by its absolute path. Returns null if unreadable. */
    readMemoryByPath(filePath: string): Promise<MemoryFile | null>;
    private resolveTierRootDir;
    private resolveMemoryDateDir;
    private isArtifactMemory;
    buildTierMemoryPath(memory: MemoryFile, tier: "hot" | "cold"): string;
    private writeMemoryFileAtomic;
    moveMemoryToPath(memory: MemoryFile, targetPath: string): Promise<void>;
    migrateMemoryToTier(memory: MemoryFile, targetTier: "hot" | "cold"): Promise<{
        changed: boolean;
        targetPath: string;
    }>;
    private get archiveDir();
    /**
     * Archive a memory by moving it from facts/ to archive/YYYY-MM-DD/.
     * Updates frontmatter with archived status before moving.
     * Returns the new file path on success, null on failure.
     */
    archiveMemory(memory: MemoryFile, lifecycle?: MemoryLifecycleEventWriteOptions): Promise<string | null>;
    readEntities(): Promise<string[]>;
    readEntity(name: string): Promise<string>;
    /** Return sorted list of entity filenames (without .md extension) */
    listEntityNames(): Promise<string[]>;
    /**
     * Find an existing entity that fuzzy-matches the proposed name.
     * Returns the existing entity filename (without .md) or null if no match.
     *
     * Matching priority:
     * 1. Exact normalized match (handled by normalizeEntityName already)
     * 2. Dehyphenated match: "jane-doe" vs "janedoe"
     * 3. Substring containment: "handle-janedoe" contains "janedoe"
     * 4. Levenshtein ≤ 2 on dehyphenated names
     */
    findMatchingEntity(proposedName: string, type: string): Promise<string | null>;
    invalidateMemory(id: string): Promise<boolean>;
    updateMemory(id: string, newContent: string, options?: {
        supersedes?: string;
        lineage?: string[];
        actor?: string;
    }): Promise<boolean>;
    /**
     * Update frontmatter fields without changing memory content.
     * Returns false when the memory is not found.
     */
    writeMemoryFrontmatter(memory: MemoryFile, patch: Partial<MemoryFrontmatter>, lifecycle?: MemoryLifecycleEventWriteOptions): Promise<boolean>;
    /**
     * Update frontmatter by memory ID.
     * Prefer writeMemoryFrontmatter(memory, patch) in batch loops to avoid full-corpus rescans.
     */
    updateMemoryFrontmatter(id: string, patch: Partial<MemoryFrontmatter>): Promise<boolean>;
    /** Remove memories past their TTL expiresAt date */
    cleanExpiredTTL(): Promise<MemoryFile[]>;
    loadBuffer(): Promise<BufferState>;
    saveBuffer(state: BufferState): Promise<void>;
    loadMeta(): Promise<MetaState>;
    saveMeta(state: MetaState): Promise<void>;
    appendMemoryActionEvents(events: MemoryActionEvent[]): Promise<number>;
    appendMemoryLifecycleEvents(events: MemoryLifecycleEvent[]): Promise<number>;
    /**
     * Append a batch of `BUFFER_SURPRISE` telemetry events (issue #563 PR 3).
     *
     * Each event records a single buffer flush decision driven by the
     * surprise gate. The ledger is consumed by
     * `reportBufferSurpriseDistribution` (Doctor report) and by downstream
     * benchmark analysis. This method is fire-and-forget by contract:
     * callers log but do not fail the hot path if the append throws.
     */
    appendBufferSurpriseEvents(events: BufferSurpriseEvent[]): Promise<number>;
    /**
     * Read the buffer-surprise ledger, most recent rows last.
     *
     * `limit` bounds the number of **valid rows** returned (not the
     * number of raw lines parsed). We parse every row, discard malformed
     * ones, then take the tail — so a partial/truncated trailing line
     * (the common failure mode after an interrupted append) cannot hide
     * otherwise-valid recent data above it.
     *
     * Non-positive / non-integer / non-finite limits return `[]` rather
     * than the entire file, matching the other ledger readers in this
     * class and protecting against `slice(-0.5)` → `slice(-0)` silently
     * devolving into an unbounded parse.
     *
     * # Performance note
     *
     * For very large ledgers (issue #563 follow-up), a tail-first reader
     * would avoid parsing the full file when only a recent window is
     * needed. We keep the full-scan implementation here because:
     *
     *   - the ledger is opt-in (flag off by default), so early deployments
     *     accumulate rows slowly;
     *   - telemetry rows are small (~200 bytes), so even 100k rows parse
     *     in well under a second;
     *   - the governance archive/cleanup flow can trim the ledger when
     *     size becomes a concern, reusing the existing maintenance hooks.
     *
     * Swap to a chunked tail-reader if production logs show this is a
     * hot path — leaving that work for a follow-up keeps this PR scoped
     * to correctness, not optimization.
     */
    readBufferSurpriseEvents(options?: {
        limit?: number;
    }): Promise<BufferSurpriseEvent[]>;
    appendBehaviorSignals(events: BehaviorSignalEvent[]): Promise<number>;
    appendReextractJobs(events: ReextractJobRequest[]): Promise<number>;
    readReextractJobs(limit?: number): Promise<ReextractJobRequest[]>;
    readBehaviorSignals(limit?: number): Promise<BehaviorSignalEvent[]>;
    readMemoryActionEvents(limit?: number): Promise<MemoryActionEvent[]>;
    readMemoryActionEventRows(limit?: number): Promise<Array<{
        line: number;
        event: MemoryActionEvent;
    }>>;
    readAllMemoryLifecycleEvents(): Promise<MemoryLifecycleEvent[]>;
    readMemoryLifecycleEvents(limit?: number): Promise<MemoryLifecycleEvent[]>;
    writeCompressionGuidelines(content: string): Promise<void>;
    readCompressionGuidelines(): Promise<string | null>;
    writeCompressionGuidelineDraft(content: string): Promise<void>;
    readCompressionGuidelineDraft(): Promise<string | null>;
    writeCompressionGuidelineOptimizerState(state: CompressionGuidelineOptimizerState): Promise<void>;
    writeCompressionGuidelineDraftState(state: CompressionGuidelineOptimizerState): Promise<void>;
    readCompressionGuidelineOptimizerState(): Promise<CompressionGuidelineOptimizerState | null>;
    readCompressionGuidelineDraftState(): Promise<CompressionGuidelineOptimizerState | null>;
    activateCompressionGuidelineDraft(options?: {
        expectedContentHash?: string;
        expectedGuidelineVersion?: number;
    }): Promise<boolean>;
    private readCompressionGuidelineStateFile;
    writeIdentityAnchor(content: string): Promise<void>;
    readIdentityAnchor(): Promise<string | null>;
    appendContinuityIncident(input: ContinuityIncidentOpenInput): Promise<ContinuityIncidentRecord>;
    readContinuityIncidents(limit?: number, state?: "open" | "closed" | "all"): Promise<ContinuityIncidentRecord[]>;
    closeContinuityIncident(id: string, closure: ContinuityIncidentCloseInput): Promise<ContinuityIncidentRecord | null>;
    writeIdentityAudit(period: "weekly" | "monthly", key: string, content: string): Promise<string>;
    readIdentityAudit(period: "weekly" | "monthly", key: string): Promise<string | null>;
    writeIdentityImprovementLoops(content: string): Promise<void>;
    readIdentityImprovementLoops(): Promise<string | null>;
    readIdentityImprovementLoopRegister(): Promise<ContinuityImprovementLoop[]>;
    upsertIdentityImprovementLoop(input: ContinuityLoopUpsertInput): Promise<ContinuityImprovementLoop>;
    reviewIdentityImprovementLoop(id: string, input: ContinuityLoopReviewInput): Promise<ContinuityImprovementLoop | null>;
    private generateId;
    private readContinuityIncidentFileNames;
    private readContinuityIncidentFile;
    private findContinuityIncidentFilePathById;
    private sanitizeIdentityAuditKey;
    writeQuestion(question: string, context: string, priority: number): Promise<string>;
    readQuestions(opts?: {
        unresolvedOnly?: boolean;
    }): Promise<Array<{
        id: string;
        question: string;
        context: string;
        priority: number;
        resolved: boolean;
        created: string;
        filePath: string;
    }>>;
    /** Invalidate the questions cache (call after writing a question). */
    invalidateQuestionsCache(): void;
    private parseQuestionFile;
    private extractFrontmatterValue;
    resolveQuestion(id: string): Promise<boolean>;
    readIdentity(workspaceDir: string, namespace?: string): Promise<string>;
    writeIdentity(workspaceDir: string, content: string, namespace?: string): Promise<void>;
    /** Max size for IDENTITY.md before we stop appending reflections (15KB leaves room under 20KB gateway limit) */
    private static readonly IDENTITY_MAX_BYTES;
    /** Minimum interval between reflections (1 hour) */
    private static readonly REFLECTION_COOLDOWN_MS;
    appendToIdentity(workspaceDir: string, reflection: string, opts?: {
        hygiene?: FileHygieneConfig;
        namespace?: string;
    }): Promise<void>;
    readIdentityReflections(): Promise<string | null>;
    writeIdentityReflections(content: string): Promise<void>;
    appendIdentityReflection(reflection: string): Promise<void>;
    /**
     * Add a relationship to an entity file.
     * Deduplicates by target+label.
     */
    addEntityRelationship(name: string, rel: EntityRelationship): Promise<void>;
    /**
     * Add an activity entry to an entity file.
     * Prepends to the beginning, prunes oldest entries beyond maxEntries.
     */
    addEntityActivity(name: string, entry: EntityActivityEntry, maxEntries: number): Promise<void>;
    /**
     * Add an alias to an entity file. Deduplicates.
     */
    addEntityAlias(name: string, alias: string): Promise<void>;
    /**
     * Set or rewrite the synthesis layer of an entity file.
     */
    updateEntitySynthesis(name: string, synthesis: string, options?: {
        entityUpdatedAt?: string;
        synthesisStructuredFactCount?: number;
        synthesisStructuredFactDigest?: string;
        synthesisTimelineCount?: number;
        updatedAt?: string;
        incrementVersion?: boolean;
    }): Promise<void>;
    /**
     * Backward-compatible alias for legacy callers/tests.
     */
    updateEntitySummary(name: string, summary: string): Promise<void>;
    readEntitySynthesisQueue(): Promise<string[]>;
    refreshEntitySynthesisQueue(): Promise<string[]>;
    removeEntitySynthesisQueueEntries(entityNames: string[]): Promise<void>;
    migrateEntityFilesToCompiledTruthTimeline(): Promise<{
        total: number;
        migrated: number;
    }>;
    /**
     * Read all entity files and return lightweight EntityFile objects.
     * Parsing is fast (~50-100ms for ~1,800 files) since entity files are small.
     */
    readAllEntityFiles(): Promise<EntityFile[]>;
    /**
     * Score an entity based on recency, frequency, activity, type priority,
     * and relationship density.
     *
     * score = recency*0.40 + frequency*0.25 + activity*0.15 + typePriority*0.10 + relationshipDensity*0.10
     */
    static scoreEntity(entity: EntityFile, now: Date): number;
    /**
     * Build the Knowledge Index: a compact markdown table of top-scored entities.
     * Respects maxEntities and maxChars limits from config.
     */
    buildKnowledgeIndex(config: PluginConfig, overrides?: {
        maxEntities?: number;
        maxChars?: number;
    }): Promise<{
        result: string;
        cached: boolean;
    }>;
    /** Invalidate the Knowledge Index cache (call after entity mutations). */
    invalidateKnowledgeIndexCache(): void;
    /** Max lines for profile.md before LLM consolidation triggers */
    private static readonly PROFILE_MAX_LINES;
    /**
     * Merge fragmented entity files that resolve to the same canonical name.
     * Preserves relationships, activity, aliases, and summary from all fragments.
     * Returns count of files merged.
     */
    mergeFragmentedEntities(): Promise<number>;
    cleanExpiredCommitments(decayDays: number): Promise<MemoryFile[]>;
    /**
     * Flush batched access tracking updates to disk.
     * Called during consolidation or when buffer exceeds max size.
     */
    flushAccessTracking(entries: AccessTrackingEntry[]): Promise<number>;
    /**
     * Get a memory by its ID.
     */
    getMemoryById(id: string): Promise<MemoryFile | null>;
    /**
     * Check which of the given memory IDs actually exist on disk.
     *
     * Uses a lightweight directory scan (collectActiveMemoryPaths) that reads
     * file names without parsing frontmatter — much cheaper than readAllMemories()
     * for simple existence checks like citation usage tracking.
     *
     * Returns the subset of `ids` that correspond to real memory files.
     */
    filterExistingMemoryIds(ids: string[]): Promise<Set<string>>;
    getProjectedMemoryState(id: string): Promise<MemoryProjectionCurrentState | null>;
    browseProjectedMemories(options: ProjectedMemoryBrowseOptions): Promise<ProjectedMemoryBrowsePage | null>;
    getProjectedGovernanceRecord(): Promise<ReturnType<typeof readProjectedGovernanceRecord>>;
    private toProjectedCurrentState;
    getMemoryTimeline(memoryId: string, limit?: number): Promise<MemoryLifecycleEvent[]>;
    /**
     * Write a memory chunk with parent reference.
     * Chunk IDs follow format: {parentId}-chunk-{index}
     */
    writeChunk(parentId: string, chunkIndex: number, chunkTotal: number, category: MemoryCategory, content: string, options?: {
        confidence?: number;
        tags?: string[];
        entityRef?: string;
        source?: string;
        importance?: ImportanceScore;
        intentGoal?: string;
        intentActionType?: string;
        intentEntityTypes?: string[];
        memoryKind?: MemoryFrontmatter["memoryKind"];
    }): Promise<string>;
    /**
     * Get all chunks for a given parent memory ID.
     * Returns chunks sorted by chunkIndex.
     */
    getChunksForParent(parentId: string): Promise<MemoryFile[]>;
    /**
     * Mark a memory as superseded by another.
     * Updates the old memory's status and adds the supersededBy link.
     */
    supersedeMemory(oldMemoryId: string, newMemoryId: string, reason: string): Promise<boolean>;
    private get summariesDir();
    /**
     * Write a memory summary.
     */
    writeSummary(summary: MemorySummary): Promise<void>;
    /**
     * Get all summaries.
     */
    readSummaries(): Promise<MemorySummary[]>;
    /**
     * Archive memories (mark as archived, not delete).
     */
    archiveMemories(memoryIds: string[], summaryId: string): Promise<number>;
    /**
     * Save topic scores to meta.json.
     */
    saveTopics(topics: TopicScore[]): Promise<void>;
    /**
     * Load topic scores from meta.json.
     */
    loadTopics(): Promise<{
        topics: TopicScore[];
        updatedAt: string | null;
    }>;
    /**
     * Add links to an existing memory.
     */
    addLinksToMemory(memoryId: string, links: MemoryLink[], lifecycle?: MemoryLifecycleEventWriteOptions): Promise<boolean>;
    private summarizeLifecycleState;
    private frontmatterPatchEventType;
    private appendGeneratedMemoryLifecycleEvent;
    private appendGeneratedMemoryLifecycleEventFailOpen;
}

export { ContentHashIndex, type MemoryLifecycleEventWriteOptions, type ReextractJobRequest, StorageManager, compareEntityTimestamps, fingerprintEntityStructuredFacts, isEntitySynthesisStale, normalizeAttributePairs, normalizeEntityName, parseEntityFile, serializeEntityFile };
