import type { ParsedScopeKey } from "./scope-contract.js";
import type { HarvestReport } from "./types.js";
import type { MemoryInjection } from "./engine.js";
/** The personal plane's shared mount under the config root (ALL projects, one home — the plane is
 *  keyed by scope, not by repo: `user:alice` is the same disk from every checkout). */
export declare function derivePersonalMemoryDir(configRoot: string): string;
export declare function derivePersonalControlDir(configRoot: string): string;
export interface ScopePlanes {
    /** proj:/legacy scopes — the repo/path-keyed plane (order preserved). */
    project: string[];
    /** user:/userproj:/org: scopes — the home-mount plane (order preserved). `org` is
     *  CENTRAL-authority (§2 表), so it routes with the personal keys — under a pinned in-repo File
     *  backend an org layer projected into the repo would leak tenant-shared memory into commit
     *  history. The mount is still the "personal" directory (one home plane; the plane is about
     *  WHERE-NOT-to-project, not about ownership — org's authority disk is the central DB anyway). */
    personal: string[];
    /** Which plane owns the write face (null = read-only layering everywhere). */
    writePlane: "project" | "personal" | null;
}
/** Classify a v2 session's scopes into planes. writeScope routes by its OWN key kind (it need not
 *  be listed in scopes — normalizeMemorySpec contract). */
export declare function classifyScopePlanes(scopes: readonly string[], writeScope: string | null): ScopePlanes;
/** True when the classified session needs the dual-root assembly at all. */
export declare function needsDualRoots(planes: ScopePlanes): boolean;
/** Convenience for the placement gate: the parsed keys that stay on the PROJECT plane. */
export declare function parsedProjectPlane(planes: ScopePlanes, writeScope: string | null): ParsedScopeKey[];
/**
 * Merge the two planes' injections into ONE block. Plane order is fixed: PROJECT first (the stable
 * prefix — repo knowledge changes less often than personal notes), PERSONAL second; the instruction
 * (trusted half, "where to write") comes from whichever plane owns the write face and leads the
 * block, exactly like the single-root layout. v1 deliberately merges at BLOCK granularity — scope
 * interleaving across planes is not reproduced (documented; the within-plane order is untouched).
 */
export declare function mergeInjections(project: MemoryInjection | undefined, personal: MemoryInjection | undefined): MemoryInjection;
/** Merge the two planes' harvest reports into the single report the runner surfaces. Counters add,
 *  lists concatenate, `ok` ANDs, the first incident wins the seat (both are still visible via the
 *  merged lists). 独立轨 F7: pass the WRITE plane's report as `a` — first-argument fields (incident
 *  seat, degraded seat) prefer `a`, and the write plane's degradation is the one that matters. */
export declare function mergeHarvestReports(a: HarvestReport, b: HarvestReport): HarvestReport;
