import type { HarvestRejection, MemoryBackend, MemoryEntry, NotePatch, PatchReport, ScanFinding } from "./types.js";
/** Default per-file byte cap — SAME value as the host engine's MAX_MEMORY_BYTES (独立轨 F3: a 60KB
 *  entry legal on the host must not be re-rejected every remote round; one cap, one truth). */
export declare const REMOTE_HARVEST_PER_FILE_BYTES: number;
/** Missing-file ratio above which the harvest refuses wholesale (engine MASS_DELETION_FUSE_RATIO). */
export declare const REMOTE_MASS_DELETION_FUSE_RATIO = 0.5;
/** File-count cap per harvest (host DEFAULT_MAX_MEMORY_FILES parity). */
export declare const REMOTE_HARVEST_MAX_FILES = 500;
/** Max DIRECTORY nesting depth below the memory root (host DEFAULT_MAX_ENTRY_DEPTH parity — the
 *  host's `scanEntryFiles` walks a subdir only while `depth + 1 <= maxDepth`, so it counts directory
 *  levels, NOT path segments: `a/b/c/note.md` (3 dirs) is accepted, `a/b/c/d/note.md` refused). */
export declare const REMOTE_HARVEST_MAX_DEPTH = 3;
export interface RemoteMemoryFile {
    /** Path RELATIVE to the sandbox memory root, `/`-separated (e.g. `pref-editor.md`, `org-acme/x.md`). */
    relPath: string;
    content: string;
}
export interface RemoteMemoryBaseline {
    writeScope: string | null;
    /** Every file materialized into the sandbox, with its commit-time identity (the CAS base). */
    files: Array<{
        relPath: string;
        id: string;
        rev: string;
        scope: string;
        readonly: boolean;
    }>;
    /** Directory names of ALL read-only layers — including ZERO-entry ones (复审 D2): the harvest's
     *  containment prefixes are otherwise inferred from `files`, so an empty inherited layer would be
     *  invisible and a planted `<dir>/new.md` would slip in as a writeScope add. Optional (additive):
     *  a baseline serialized before this field keeps the files-inferred prefixes only. */
    readonlyDirs?: string[];
}
export interface RemoteMaterialization {
    /** Ship these into the sandbox memory root (the deployment owns the transport). `readonly` is the
     *  session's policy, enforced by {@link harvestFilesToPatches}' `readonly_layer` rejection; whether
     *  to also set permission bits on its own volume is the deployment's call — the engine sets none. */
    files: Array<RemoteMemoryFile & {
        readonly: boolean;
    }>;
    /** Keep this (serializable) and pass it to {@link harvestFilesToPatches} at harvest time. */
    baseline: RemoteMemoryBaseline;
}
/**
 * Project backend entries into a shippable file list. Layout mirrors the host engine: the
 * writeScope's entries sit at the memory root, every other scope under `<scopeDirName>/`
 * (read-only inherited layers). Excluded: budget stubs (a remote v1 materializes full bodies only)
 * and the derived MEMORY.md index (the deployment may render its own).
 */
export declare function materializeEntriesToFiles(backend: MemoryBackend, scopes: readonly string[], writeScope: string | null): Promise<RemoteMaterialization>;
export interface RemoteHarvestResult {
    /** Feed to `backend.applyPatches` (the deployment owns the call + the resulting PatchReport). */
    patches: NotePatch[];
    rejections: HarvestRejection[];
    /** Baseline files absent from the read-back set (info; NEVER a delete — tombstones only). */
    missing: string[];
    /** Set instead of patches when the mass-deletion fuse trips (deployment surfaces it, human call). */
    incident?: {
        kind: "mass_deletion";
        detail: string;
    };
    /** Canonical projections (minted ids / completed frontmatter) the deployment SHOULD write back into
     *  the sandbox after the backend commit succeeds, keyed by relPath — same promotion discipline as
     *  the host engine (project only what applied; see {@link projectionsToWriteBack}). */
    projections: Array<{
        relPath: string;
        entry: MemoryEntry;
        content: string;
    }>;
}
/**
 * The pure gate+diff core over files read back from a remote sandbox. Same judgment order as the
 * host engine's harvest: readonly-layer tamper → rejection (restore is the deployment's I/O);
 * missing + fuse; per-file size cap → scan rule set (secret/injection/filename) → parse →
 * id-immutability (baseline id wins) → tombstone-only delete → CAS update / rename / add.
 */
export declare function harvestFilesToPatches(baseline: RemoteMemoryBaseline, files: readonly RemoteMemoryFile[], opts?: {
    perFileBytes?: number;
    massDeletionFuseRatio?: number;
    maxFiles?: number;
    maxDepth?: number;
    now?: () => number;
}): RemoteHarvestResult;
/** After `backend.applyPatches(result.patches)`, the projections worth writing back into the sandbox:
 *  only those whose (id, non-delete op) actually APPLIED — the host engine's promotion discipline. */
export declare function projectionsToWriteBack(result: RemoteHarvestResult, report: PatchReport): Array<{
    relPath: string;
    content: string;
}>;
export interface InboundEntryFinding {
    id: string;
    findings: ScanFinding[];
}
/**
 * design/142 §3③ — the central-side inbound gate as a PURE function. A sync channel is a write path
 * that bypasses the harvest gate by construction (same class as git pull, §2.7): before entries from
 * another plane touch an authority disk, screen body + slug + size with the SAME rule set the
 * harvest gate runs. Gate logic single-sourced in core; the execution seat rides the data plane
 * (service calls this in its write face). Returns findings per OFFENDING entry only — empty array =
 * the batch is clean.
 */
export declare function screenInboundEntries(entries: readonly MemoryEntry[], opts?: {
    perFileBytes?: number;
}): InboundEntryFinding[];
