/**
 * Mesh Task Ledger — GasTown-inspired append-only JSONL task history
 *
 * Records all mesh orchestration events (task dispatch, completion, failure,
 * checkpoint, node lifecycle) as an append-only JSONL file per mesh.
 *
 * Inspired by GasTown's "Beads" pattern: every action is a versioned record
 * that persists across agent sessions, enabling recovery, auditing, and
 * continuity when individual sessions fail or context windows are exhausted.
 *
 * Storage: ~/.adhdev/mesh-ledger/<meshId>.jsonl
 * Format:  One JSON object per line, newest entries appended at end
 * Safety:  mode 0o600, atomic append via appendFileSync
 */
import { EventEmitter } from 'events';
import { MeshRuntimeStore } from './mesh-runtime-store.js';
import { type MeshLedgerOriginatingCoordinatorV2 } from './contracts.js';
export type MeshLedgerKind = 'task_dispatched' | 'task_completed' | 'task_failed' | 'task_stalled' | 'task_approval_needed' | 'p2p_dispatch_failed' | 'session_launched' | 'session_auto_launch' | 'session_stopped' | 'checkpoint_created' | 'node_cloned' | 'node_joined' | 'node_removed' | 'coordinator_started' | 'recovery_attempted' | 'ledger_replicated' | 'ledger_reconciled' | 'direct_fast_forward' | 'delivery_unroutable' | 'direct_dispatch_pruned' | 'event_held' | 'event_held_requeued' | 'task_reclaimed' | 'coordinator_operating_note' | 'coordinator_operating_note_tombstone' | 'mission_created' | 'mission_status_changed' | 'mission_goal_updated' | 'magi_dispatched' | 'magi_synthesis' | 'key_injection';
export interface MeshLedgerEntry {
    id: string;
    meshId: string;
    timestamp: string;
    kind: MeshLedgerKind;
    nodeId?: string;
    sessionId?: string;
    providerType?: string;
    payload: Record<string, unknown>;
}
export declare function isIntentionalCleanupStopEntry(entry: Pick<MeshLedgerEntry, 'kind' | 'payload'>): boolean;
export type MeshWorkerResultStatus = 'completed' | 'failed' | 'blocked' | 'partial' | 'unknown';
export type MeshProcessArtifactKind = 'process' | 'log' | 'port' | 'window' | 'session' | 'file' | 'url' | 'other';
export interface MeshValidationResultArtifact {
    command?: string;
    status: 'passed' | 'failed' | 'skipped' | 'unknown';
    durationMs?: number;
    outputPath?: string;
    summary?: string;
}
export interface MeshProcessArtifact {
    kind: MeshProcessArtifactKind;
    id?: string;
    label?: string;
    locator?: string;
    pid?: number;
    port?: number;
    url?: string;
    path?: string;
    sessionId?: string;
    keepRunning?: boolean;
    metadata?: Record<string, unknown>;
}
export interface MeshWorkerResultArtifact {
    status: MeshWorkerResultStatus;
    classification?: string;
    changedFiles: string[];
    validationResults: MeshValidationResultArtifact[];
    gitStatus?: Record<string, unknown>;
    processArtifacts: MeshProcessArtifact[];
    errors: string[];
    nextAction?: string;
    requiresUserAction: boolean;
    source: 'explicit_metadata' | 'final_summary_json' | 'parseable_answer' | 'default';
}
export interface MeshTaskCompletionEvidence {
    source: 'agent_status_event';
    event: 'agent:generating_completed' | 'agent:ready';
    nodeId: string;
    sessionId: string;
    providerType?: string;
    completedAt: string;
    transcriptHandle: {
        kind: 'provider_session' | 'runtime_session';
        sessionId: string;
        providerSessionId?: string;
        finalSummaryAvailable: boolean;
    };
    workerResult: MeshWorkerResultArtifact;
    git: {
        status: 'deferred';
        reason: string;
    };
    validation: {
        status: 'deferred';
        commandsRun: string[];
        reason: string;
    };
    checkpoint: {
        attempted: false;
        reason: 'not_attempted_for_ordinary_completion';
    };
}
export interface BuildTaskCompletionEvidenceOptions {
    event: MeshTaskCompletionEvidence['event'];
    nodeId: string;
    sessionId: string;
    providerType?: string;
    providerSessionId?: string;
    finalSummary?: string;
    workerResult?: Record<string, unknown>;
    completedAt?: string;
}
export interface MeshLedgerSummary {
    meshId: string;
    totalEntries: number;
    taskDispatched: number;
    taskCompleted: number;
    taskFailed: number;
    taskStalled: number;
    sessionLaunched: number;
    checkpointCreated: number;
    lastActivityAt: string | null;
    recentFailures: number;
}
export interface ReadLedgerOptions {
    tail?: number;
    since?: string;
    kind?: MeshLedgerKind[];
    /**
     * Filter to entries whose nodeId is equivalent to this daemon id. Matched via
     * daemonIdsEquivalent (not raw ===) so caller-supplied identifiers in any form
     * (mach_X vs daemon_mach_X) resolve correctly — see the canon-identity defect class.
     */
    node?: string;
}
export interface ReadLedgerSliceOptions {
    /** Return entries strictly after this entry id. If not found, starts from the beginning of the filtered set. */
    afterId?: string;
    /** Return entries at or after this timestamp. */
    since?: string;
    /** Optional event kind filter. */
    kind?: MeshLedgerKind[];
    /** Maximum entries to return. Clamped to a bounded protocol maximum. */
    limit?: number;
}
export interface MeshLedgerCursor {
    afterId: string | null;
    nextAfterId: string | null;
    limit: number;
    hasMore: boolean;
}
export interface MeshLedgerSlice {
    protocol: 'adhdev.mesh.ledger.slice.v1';
    meshId: string;
    entries: MeshLedgerEntry[];
    cursor: MeshLedgerCursor;
    summary: MeshLedgerSummary;
    sourceOfTruth: {
        kind: 'local_jsonl';
        path: string;
        bounded: true;
        maxLimit: number;
    };
}
export interface AppendRemoteLedgerResult {
    accepted: number;
    skippedDuplicate: number;
    rejectedInvalid: number;
    entries: MeshLedgerEntry[];
}
export declare const MAX_LEDGER_SLICE_LIMIT = 500;
export declare const OPERATING_NOTE_KIND: MeshLedgerKind;
export declare const OPERATING_NOTE_TOMBSTONE_KIND: MeshLedgerKind;
export declare const OPERATING_NOTE_DEDUPE_WINDOW = 40;
export declare const OPERATING_NOTE_KEEP_LATEST = 100;
export declare function getLedgerDir(): string;
/**
 * Footer to append to worker task messages so workers output structured results
 * that the daemon parses via extractJsonObjectFromSummary / normalizeMeshWorkerResult.
 *
 * Usage: append buildWorkerTaskFooter() to the task message in mesh_send_task /
 * mesh_enqueue_task. The coordinator prompt rules instruct coordinators to do this.
 */
export declare function buildWorkerTaskFooter(): string;
/**
 * Compact the active ledger file for a mesh by moving old terminal entries
 * (task_completed, task_failed, task_stalled, recovery_attempted older than 7 days)
 * to <meshId>.archive.jsonl, keeping the active file lean.
 *
 * Non-terminal entries (dispatch, sessions, node lifecycle) are always retained.
 * Called automatically from appendLedgerEntry when the file exceeds COMPACT_THRESHOLD_BYTES.
 */
export declare function compactLedger(meshId: string): {
    archivedCount: number;
    retainedCount: number;
};
export declare function normalizeMeshWorkerResult(input?: Record<string, unknown>, source?: MeshWorkerResultArtifact['source']): MeshWorkerResultArtifact;
export declare function buildTaskCompletionEvidence(opts: BuildTaskCompletionEvidenceOptions): MeshTaskCompletionEvidence;
/**
 * Build the v2 originating-coordinator stamp for a task_dispatched ledger entry
 * (B2a / design decision §2). This is the source of truth from which a worker's
 * completion emit later restores `dispatchedBy` — it records which coordinator
 * dispatched the task, so the terminal event can be routed (unicast) back to it.
 *
 * Nested under `payload.originatingCoordinator`; additive, so existing readers
 * of the task_dispatched payload are unaffected. Returns undefined when no
 * coordinator daemon id is known (the pre-v2 path) so the caller omits the stamp
 * entirely rather than writing a malformed identity — those entries stay v1 and
 * are broadcast-treated during rollout.
 */
export declare function buildLedgerOriginatingCoordinatorStamp(fields: {
    coordinatorDaemonId?: string | null;
    coordinatorRunId?: string | null;
    coordinatorSessionId?: string | null;
}): MeshLedgerOriginatingCoordinatorV2 | undefined;
/**
 * Append a new entry to the mesh ledger.
 * Handles file creation, rotation on size overflow, and atomic writes.
 */
export declare const meshLedgerEvents: EventEmitter<[never]>;
export declare function appendLedgerEntry(meshId: string, partial: Omit<MeshLedgerEntry, 'id' | 'meshId' | 'timestamp'>): MeshLedgerEntry;
/** True if the operating note is retracted by any tombstone in `tombstones`. */
export declare function isOperatingNoteTombstoned(entry: Pick<MeshLedgerEntry, 'id' | 'payload'>, tombstones: {
    ids: Set<string>;
    fingerprints: Set<string>;
}): boolean;
/**
 * Fix (2) supersede/remove: append a tombstone that retracts a coordinator
 * operating note. Targets by note id and/or by exact trimmed text (a text target
 * retracts every note with that text). History is preserved — the notes stay in
 * the ledger but readers filter them out. Returns how many currently-live notes
 * the tombstone will hide.
 */
export declare function tombstoneOperatingNote(meshId: string, target: {
    noteId?: string;
    text?: string;
    reason?: string;
}): {
    tombstone: MeshLedgerEntry;
    matched: number;
};
/**
 * Read live operating notes (tombstoned notes filtered out), oldest→newest.
 * `tail` bounds the number of live notes returned (the freshest N).
 */
export declare function readOperatingNotes(meshId: string, opts?: {
    tail?: number;
}): MeshLedgerEntry[];
/**
 * Fix (3) keep-latest-N prune for coordinator_operating_note. Removes, from the
 * store, (a) every note retracted by a tombstone, and (b) the oldest live notes
 * beyond `keepLatest`. Tombstone entries themselves are retained as an audit trail
 * of what was forgotten. Returns the number of note entries removed.
 */
export declare function pruneOperatingNotes(meshId: string, keepLatest?: number): number;
/**
 * Append entries received over local-first/P2P ledger replication to the local ledger.
 * This skips deduplicated entries and rejects malformed/cross-mesh entries.
 */
export declare function appendRemoteLedgerEntries(meshId: string, entries: MeshLedgerEntry[]): AppendRemoteLedgerResult;
/**
 * Test helper: clear all runtime ledger state for a mesh — SQLite rows, read
 * cache, and the one-time import flag. JSONL files are the caller's concern.
 */
export declare function __clearMeshLedgerForTests(meshId: string): void;
/**
 * Read ledger entries with optional filtering.
 * G2: SQLite (mesh_event_ledger) is the primary read path; legacy JSONL is
 * imported once per store instance and otherwise retained as an
 * export/import/debug artifact only.
 */
export declare function readLedgerEntries(meshId: string, opts?: ReadLedgerOptions): MeshLedgerEntry[];
/**
 * Read a bounded, cursor-addressable ledger slice for local-first/P2P replication.
 * The result is intentionally small and self-describing so coordinators can query
 * remote daemons on demand without Cloud/D1 becoming a ledger data-plane.
 */
export declare function readLedgerSlice(meshId: string, opts?: ReadLedgerSliceOptions): MeshLedgerSlice;
/**
 * G4: Read a bounded ledger slice from the SQLite mesh_event_ledger table.
 * This is the preferred P2P reconcile read path; JSONL files are retained as
 * export/import/debug/legacy artifacts only.
 *
 * Returns a shape structurally compatible with MeshLedgerSlice (minus the
 * JSONL-specific `summary` and `sourceOfTruth.path` fields) so callers can
 * pass it to buildMeshLedgerReplicaEvidence without modification.
 */
export declare function readLedgerSliceFromStore(meshId: string, opts?: ReadLedgerSliceOptions): ReturnType<typeof MeshRuntimeStore.prototype.readLedgerSlice>;
/**
 * Get a summary of mesh activity from the ledger.
 */
export declare function getLedgerSummary(meshId: string): MeshLedgerSummary;
export interface SessionRecoveryContext {
    /** The original task message that was dispatched to this session/node */
    lastTaskMessage: string | null;
    /** The node that was running the failed task */
    failedNodeId: string | null;
    /** Session ID of the failed session */
    failedSessionId: string | null;
    /** Provider used for the failed session */
    failedProviderType: string | null;
    /** Number of consecutive failures for this node (within recent window) */
    consecutiveNodeFailures: number;
    /** Number of times this specific task was attempted (matched by truncated message prefix) */
    taskAttemptCount: number;
    /** Whether a retry is recommended based on maxRetries policy */
    retryRecommended: boolean;
    /** Human-readable recovery advice for the coordinator */
    advice: string;
}
/**
 * Build recovery context for a failed session.
 * Looks up the ledger to find the original task, count failures, and advise on retry.
 */
export declare function getSessionRecoveryContext(meshId: string, opts: {
    sessionId?: string;
    nodeId?: string;
    maxRetries?: number;
}): SessionRecoveryContext;
