import { type MemoryEntry, type MemoryEntryDistilled, type MemoryEntryFrontmatter, type MemoryEntryOrigin } from "./types.js";
/** A parsed entry file: frontmatter (may be absent — CC allows bare files; harvest mints them) + body. */
export interface ParsedEntryFile {
    /** The hidden immutable id (`id:` frontmatter line), when present. */
    id?: string;
    frontmatter: MemoryEntryFrontmatter;
    body: string;
    /** True when the file had a well-formed `---` frontmatter block at all. */
    hadFrontmatter: boolean;
    /** Present (`true`) only when the file OPENS a frontmatter block that no whole-line closing fence ever closes — reported
     *  with `hadFrontmatter: false` (nothing is read out of the block), and told apart here from a file that never had one,
     *  for a caller that must refuse it by name ({@link UNCLOSED_MEMORY_FILE_REASON}). */
    unclosed?: true;
}
/** The id-shape contract, shared with the WRITE path (KNOWN-ISSUES 幽灵行加固): the File backend's
 *  applyPatches refuses any patch whose id this rejects — such an entry would be applied + ledgered,
 *  yet THIS parser drops the id on read (a fresh one gets minted), leaving the file on disk but the
 *  id permanently invisible. Read gate and write gate must stay one predicate. */
export declare function isValidEntryId(value: string): boolean;
/** The harvest's refusal sentence for a file {@link ParsedEntryFile.unclosed} names: the shared reason, and what the author does about it. */
export declare const UNCLOSED_MEMORY_FILE_REASON = "memory file opens with --- but is not closed by a whole-line --- (rejected, NOT harvested as a file without frontmatter); close the block with a line that is exactly ---";
/** Parse one memory file's text into frontmatter + body. Never throws — an unfenced file is all-body. */
export declare function parseEntryFile(text: string): ParsedEntryFile;
/** Serialize an entry to its canonical file projection (id FIRST — the hidden immutable field). */
export declare function serializeEntryFile(entry: Pick<MemoryEntry, "id" | "frontmatter" | "body">): string;
/**
 * Content-hash rev (the CAS baseline). Computed over the SEMANTIC content — id, structured
 * frontmatter fields, preserved extra lines, and body — via a canonical JSON tuple, NOT raw file
 * bytes: engine (parsing disk files) and backend (storing entries) must agree on the rev regardless
 * of incidental serialization formatting, or every materialize would see a phantom diff.
 */
export declare function computeEntryRev(entry: Pick<MemoryEntry, "id" | "frontmatter" | "body">): string;
/** True ⇔ `extra` carries origin-form bytes (an invalid/foreign origin block preserved verbatim,
 *  or an origin block a pre-336 vintage folded into `extra`). */
export declare function hasOriginFormExtra(fm: Pick<MemoryEntryFrontmatter, "extra">): boolean;
/**
 * design/336 slice 2 — the ONE serialization-closed tokenization of `extra`'s origin-form bytes
 * (the adversarial round-3 deep fix; every predicate below reads THROUGH this walk, never through
 * a private re-implementation). A CARRIER is one independent origin representation:
 *  - a bare block header (`origin:` — judged on the TRIMMED line, so indented spellings count),
 *    together with its indented continuation lines: ONE carrier, normalized field-by-field
 *    (first-wins per key; unknown sub-lines tolerated — an in-block `origin: …` scalar is part of
 *    THIS carrier, never its own);
 *  - a scalar `origin: …` line OUTSIDE any block: ONE carrier, always the sentinel (a scalar names
 *    no fields).
 * Per-carrier normalization is INDEPENDENT on purpose (adversarial round 2: a cross-carrier
 * accumulation let two individually-invalid blocks combine into a valid marker, and parse-time
 * block reordering then changed which fields won): a carrier whose own fields form a valid origin
 * (taint external, `at` present AND serialization-stable, cause absent-or-known) normalizes to
 * that value; anything else normalizes to the `{ taint: "external", at: 0 }` sentinel (cause
 * absent, `at` = 0 — a clock here would make engine and backend normalize to different values and
 * the engine's own patches would never converge). Marker-form bytes are NEVER dropped and NEVER
 * read as clean absence.
 */
export declare function extraOriginCarriers(extra: readonly string[] | undefined): MemoryEntryOrigin[];
/**
 * design/336 §2.2 — the ONE reading of an entry's committed external-origin marker: the typed
 * field when present, else the first `extra` carrier's deterministic normalization
 * ({@link extraOriginCarriers}). Returns `undefined` ⇔ the entry carries no marker in any form.
 * The first-carrier choice is immaterial on every committable shape: a representation whose
 * carriers DISAGREE is refused at every inbound boundary ({@link ambiguousOriginRepresentation}),
 * so a committed multi-carrier shape always answers the one agreed value.
 */
export declare function committedOriginOf(fm: Pick<MemoryEntryFrontmatter, "origin" | "extra">): MemoryEntryOrigin | undefined;
/**
 * design/383 §1.6 — the CONSOLIDATION exposure predicate: is this entry's content untrusted for
 * the purpose of the distillation fold? TWO axes, not one:
 *  - a committed external-origin marker ({@link committedOriginOf}) — the design/336 axis;
 *  - `trust: "untrusted"` — the design-A C-5 repo-ingest marker, which an ingested repo file can
 *    carry with NO origin marker at all. Such an entry is untrusted content by the same law that
 *    makes it un-whitewashable (the single-value marker has no `"trusted"` spelling to escalate
 *    to), and the origin-only predicate sorted it into the CLEAN arm — its bytes then authored
 *    clean products, and those products committed unmarked. That is exactly the marked-ingress
 *    laundering window the exposure partition exists to close.
 *
 * The direction is deliberately conservative (over-marking): an entry judged marked here is
 * withheld from the clean arm and its products carry `external/derived`. Nothing here proves an
 * unmarked entry clean — absence of both markers means "never judged exposed", as always.
 *
 * This is the consolidation lane's judgment only. The READ-face treatment (opaque handles, band
 * ordering, the `MemoryEntryHeader.exposure` backend fact) stays on the origin axis alone: those
 * faces answer "does the store carry an origin marker", a data question a third-party backend
 * already answers, and widening them is a backend-contract change this predicate does not make.
 */
export declare function consolidationExposedFrontmatter(fm: Pick<MemoryEntryFrontmatter, "origin" | "extra" | "trust">): boolean;
/** Deep equality over the origin marker (every member, absence included) — the immutability law's
 *  comparator: a downgraded cause or a rewritten `at` is as refused as a strip. */
export declare function originEquals(a: MemoryEntryOrigin | undefined, b: MemoryEntryOrigin | undefined): boolean;
/**
 * design/336 (adversarial rounds 1-3) — the AMBIGUOUS origin-representation predicate, ONE law for
 * every inbound boundary (backend patch law, sync wire, bundle validation, out-of-band adoption):
 * a representation is refused ⇔ its carriers DISAGREE — any two of {the typed field, each `extra`
 * carrier's independent normalization ({@link extraOriginCarriers})} differ on any member — or the
 * typed `at` is not serialization-stable (a value that cannot survive its own serialization is a
 * representation conflict with the entry's next parse). Covered vehicles: typed A + disagreeing
 * extra block B (round 1 — the typed member satisfies the immutability comparator while B rides
 * into storage and a reparse answers B); disagreeing extra-only blocks (round 2 — cross-block
 * field combination plus parse-time block reordering rewrite members with no typed origin at all).
 *
 * The refusal boundary keys on DISAGREEMENT, not on carrier count (slice-2 serialization closure,
 * the round-3 deep fix): agreeing carriers are never a member-rewrite vehicle — refusing them by
 * count alone made the verdict flip across a serialize/parse cycle (a promotion reseats one
 * carrier without changing any value). This generalizes the old "typed beside EXACTLY ONE equal
 * extra form" legacy-carriage exception: N agreeing representations are that same carriage, so
 * carry-forward of old committed forms never bricks. The model-writable face never reaches this
 * predicate — the harvest strips every origin form and re-judges (§2.3-1). Together with the
 * pristine-only typed seating (parse) and the carrier-canonical rev ({@link computeEntryRev}),
 * the accepted set is SERIALIZATION-CLOSED: carrier count, normalized origin, ambiguity verdict
 * and rev are all invariant across serialize/parse at every boundary (property-tested).
 */
export declare function ambiguousOriginRepresentation(fm: Pick<MemoryEntryFrontmatter, "origin" | "extra">): boolean;
/**
 * design/336 §2.3-1 — the harvest-side STRIP of model-written origin bytes (typed field AND
 * origin-form `extra` lines, a block header's indented continuation included). The origin seat is
 * engine-authored in every mode: whatever a file on the model-writable plane says about its own
 * origin is not evidence — the engine strips it and mints (or carries forward) its own judgment.
 * Same family as the invalid-id "dropped, fresh one minted" exception to the round-trip law.
 * MUTATES the given (already-copied) frontmatter; returns true ⇔ anything was stripped (the
 * caller discloses via a report warning).
 */
export declare function stripModelWrittenOrigin(fm: MemoryEntryFrontmatter): boolean;
/** True ⇔ `extra` carries distilled-form bytes (a non-pristine/foreign block preserved verbatim). */
export declare function hasDistilledFormExtra(fm: Pick<MemoryEntryFrontmatter, "extra">): boolean;
/** The ONE reading of an entry's committed distilled block: the typed seat or nothing. Extra-form
 *  bytes deliberately do NOT answer here (they mint no edge — fewer edges is the safe direction
 *  for a suppression carrier). Returns a defensive copy. */
export declare function committedDistilledOf(fm: Pick<MemoryEntryFrontmatter, "distilled">): MemoryEntryDistilled | undefined;
/** Deep equality over the distilled block (every member, input order included) — the immutability
 *  law's comparator: a rewritten carrierRev, a dropped input row or a flipped superseded flag is as
 *  refused as a strip. */
export declare function distilledEquals(a: MemoryEntryDistilled | undefined, b: MemoryEntryDistilled | undefined): boolean;
/**
 * design/339 §1.4.2-1 — the harvest-side STRIP of model-written distilled bytes (typed field AND
 * distilled-form `extra` lines): the block is minted by the consolidation plan freeze EXCLUSIVELY —
 * whatever a file on the model-writable plane says about its own lineage/supersession is not
 * evidence (a model-writable edge would be the covert-delete channel add-only exists to close).
 * Same seat and same disclosure discipline as {@link stripModelWrittenOrigin}. MUTATES the given
 * (already-copied) frontmatter; returns true ⇔ anything was stripped.
 */
export declare function stripModelWrittenDistilled(fm: MemoryEntryFrontmatter): boolean;
/** Parse a file's text directly into a full MemoryEntry (id must already be present/decided). */
export declare function entryFromFile(text: string, id: string, slug: string, scope: string): MemoryEntry;
