/**
 * EvolutionActionsReplicatedStore — the FIFTH concrete consumer of the HLC replicated-store
 * foundation (WS2.5) and the FOURTH memory-family kind (after WS2.4 knowledge, WS2.2
 * learnings, and WS2.3 relationships). It layers the `evolution-action-record` replicated
 * kind onto the generic substrate (ReplicatedRecordEnvelope / UnionReader / ConflictStore /
 * RollbackUnmerge / ReplicationBudget / StoreSnapshot) so that a self-improvement ACTION the
 * agent raised on machine A is known on machine B — ONE action queue, not one-per-machine.
 *
 * It is the literal analog of `KnowledgeReplicatedStore.ts` (the WS2.4 reference consumer)
 * and `LearningsReplicatedStore.ts` (the WS2.2 memory-family sibling). An action is a WORK
 * ITEM (a tracked thing the agent committed to do), lower-PII than a relationship — but its
 * `description`/`commitTo` CAN name a person or a platform, so it REUSES the established PII
 * machinery (type-clamp, disclosure-min projection, tombstones, flag-coherence) rather than
 * reinventing or downgrading it. THIS IS PURE LOGIC. No fs, no Date directly, no network. It
 * defines:
 *
 *   A. The `evolution-action-record` store schema — a STRICT typed validator that
 *      TYPE-CLAMPS every known field: `createdAt`/`dueBy`/`completedAt` ISO-8601-or-absent,
 *      `priority` ∈ the {critical,high,medium,low} enum, `status` ∈ the
 *      {pending,in_progress,completed,cancelled} enum, `tags[]`/free text length-clamped.
 *      The schema is a DISCRIMINATED UNION on `op` — an `op:'put'` VALUE schema AND an
 *      `op:'delete'` TOMBSTONE schema coexist under the one kind, so a tombstone is never
 *      marked invalid by the value schema.
 *
 *   B. The disclosure-minimized PROJECTION (fork #1/#2) — `buildEvolutionActionRecordData`
 *      emits ONLY the enumerated action fields, NEVER the local generated `ACT-NNN` id.
 *      `recordKey` is the cross-machine IDENTITY SURFACE, derived deterministically from the
 *      stable content (normalize(title) + normalize(commitTo) + createdAt) — never the
 *      per-machine, sequentially-assigned `ACT-NNN` id (the cross-machine-UNSTABLE id,
 *      exactly the relationship-UUID / LRN-id trap the prior kinds solved with a stable
 *      identity surface). The SAME committed action on two machines collapses to ONE record.
 *
 *   C. The TOMBSTONE builder — `buildEvolutionActionTombstoneData` emits an `op:'delete'`
 *      record `{ recordKey, op, hlc, origin, deletedAt }` so an actual queue-REMOVAL
 *      propagates as a positive signal across an offline-then-rejoining peer instead of a
 *      record absence. CRITICAL: a `completed`/`cancelled` action is a TERMINAL state — its
 *      record is RETAINED (history), NOT tombstoned. Only an action that is actually REMOVED
 *      from the queue (the prune-over-maxActions path) emits a tombstone; else a peer
 *      re-replicates the locally-removed action forever (resurrection).
 *
 *   D. The union-aware read — `mergeUnionToActions` collapses a
 *      `Map<recordKey, UnionResult>` into the merged action view. Actions are HIGH-impact at
 *      the REPLICATION layer (a concurrent divergent VALUE edit to the SAME recordKey — e.g.
 *      machine A marks an action `completed` while B still has it `in_progress` — goes through
 *      APPEND-BOTH-AND-FLAG; both versions surface, never a silent clobber). The CONSUMER
 *      READ path is ADVISORY (fork #3): it injects BOTH variants of an open conflict as
 *      guidance — an action is a work item to surface, not authority — and NEVER blocks on an
 *      unresolved conflict. The read NEVER writes a foreign record into the local store.
 *
 *   E. Foreign-record render safety — `renderForeignActionContext` wraps a replicated record
 *      in an explicit `<replicated-untrusted-data origin="…">` envelope and sanitizes EVERY
 *      rendered field. There is no "trusted because machine-set" render slot for a foreign
 *      record.
 *
 * DECIDED FORKS (Echo, 2026-06-13 — recorded verbatim in the PR ELI16):
 *   1. recordKey = a content fingerprint over the STABLE action identity
 *      (sha256(normalize(title) + '\x1f' + normalize(commitTo || '') + '\x1f' + createdAt)),
 *      NEVER the local `ACT-NNN` id (cross-machine identity surface — see
 *      deriveEvolutionActionRecordKey).
 *   2. `status`/`completedAt`/`priority` are MUTABLE fields → last-writer-witness wins; a
 *      concurrent divergence rides the SAME append-both-and-flag path (NOT a special CRDT
 *      merge). The canonical case: A marks an action `completed` while B still has it
 *      `in_progress` — the witness-ordered later write wins; a genuine concurrent divergence
 *      surfaces both states. A `completed`/`cancelled` action is a TERMINAL state — its record
 *      is retained (history), NOT tombstoned; only an actual queue-REMOVAL tombstones. A
 *      status change MUST re-emit (the whole point — a peer must SEE an action was already
 *      completed elsewhere so it does not redo it).
 *   3. Impact tier = HIGH at the REPLICATION layer (append-both-and-flag), ADVISORY at the
 *      READ layer (both variants injected as hints, never blocking) — see mergeUnionToActions
 *      + EVOLUTION_ACTION_IMPACT_TIER.
 *
 * SAFETY POSTURE: MECHANISM, dark by default. Nothing here blocks a user-initiated action.
 * The local `ACT-NNN` id is NEVER part of the replicated schema and is stripped from every
 * emitted projection (disclosure minimization).
 */
import type { ActionItem } from './types.js';
import type { StoreFieldSchema, ReplicatedEnvelope } from './ReplicatedRecordEnvelope.js';
import type { ImpactTier, OriginRecord, UnionResult } from './UnionReader.js';
import type { ReplicatedKindBounds } from './ReplicationBudget.js';
import type { HlcTimestamp } from './HybridLogicalClock.js';
/** The stateSync config sub-key + advert suffix for this store (e.g.
 *  `multiMachine.stateSync.evolutionActions.enabled`). Equal to the advert flag key
 *  `stateSyncReceive['evolutionActions']`. */
export declare const EVOLUTION_ACTION_STORE_KEY = "evolutionActions";
/** The JournalKind string this store rides — the DUAL-REGISTRY's dynamic half.
 *  MUST also be present in CoherenceJournal.JOURNAL_KINDS (the static half), or the
 *  store advertises receive=true yet serves/applies/pulls nothing. */
export declare const EVOLUTION_ACTION_RECORD_KIND = "evolution-action-record";
/**
 * Evolution actions are HIGH-impact at the REPLICATION layer (fork #3): a concurrent
 * divergent VALUE edit to the SAME recordKey from different origins goes through
 * APPEND-BOTH-AND-FLAG — both versions preserved, ONE deduped conflict, never a silent
 * overwrite. The READ path (mergeUnionToActions) is ADVISORY — both variants surface as
 * guidance hints, the read never blocks on an open conflict — an action is a work item to
 * surface, not authority. Operator resolution via POST /state/resolve-conflict is OPTIONAL
 * cleanup that collapses the flag, never a gate on the hint.
 */
export declare const EVOLUTION_ACTION_IMPACT_TIER: ImpactTier;
/** The valid `priority` enum for an action (ActionItem.priority). A foreign record whose
 *  `priority` is outside this set is REJECTED (markup cannot survive an enum slot). */
export declare const EVOLUTION_ACTION_PRIORITIES: ReadonlyArray<string>;
/** The valid `status` enum for an action (ActionItem.status). A foreign record whose
 *  `status` is outside this set is REJECTED. This is the load-bearing cross-machine field
 *  (fork #2) — a peer must SEE that an action was already completed/in_progress elsewhere. */
export declare const EVOLUTION_ACTION_STATUSES: ReadonlyArray<string>;
/** An action `description` can be a paragraph (a full commitment write-up). Clamp on receive. */
export declare const MAX_DESCRIPTION_LENGTH = 20000;
/** Per-free-text-string clamp for title / commitTo / resolution / each tag / each source
 *  sub-field. */
export declare const MAX_FREETEXT_LENGTH = 2000;
/** Tags cap (mirrors a reasonable per-action tag count). */
export declare const MAX_TAGS = 50;
/**
 * Per-kind replication bounds. The actions store is FEW + bounded (the EvolutionManager
 * prunes to maxActions=300), so the per-store retention mirrors the learning-record /
 * knowledge-record siblings (a small window with a few archives). NEVER `rotateKeep: 0`
 * (rotate-but-never-delete would be a compliance defect for any memory-family kind). The
 * rate cap COALESCES (latest state per recordKey per interval) so a churny
 * add/updateAction loop does not flood the stream.
 */
export declare const EVOLUTION_ACTION_RECORD_BOUNDS: ReplicatedKindBounds;
/**
 * Per-entry size cap RAISED to 64KB for this kind. The default
 * APPLIER_MAX_ENTRY_BYTES = 8KB is SMALLER than a fat action (a 20K description alone
 * exceeds it), so under it the longest actions would never replicate AND would wedge the
 * stream. 64KB is provably above the disclosure-minimized projection's maximum:
 * description(20k) is the dominant term — we additionally enforce a HARD post-projection
 * ceiling: a record that STILL exceeds 64KB after projection is REJECTED with a named
 * error (never silent-truncate, never suspect-wedge). See assertProjectionUnderCap.
 */
export declare const EVOLUTION_ACTION_MAX_ENTRY_BYTES: number;
/**
 * The store-specific field names the `evolution-action-record` VALUE schema OWNS (the
 * unknown-field counter's allowlist). The local `ACT-NNN` id is DELIBERATELY ABSENT — it
 * is per-machine + sequential and never replicated (the recordKey keys on the content
 * fingerprint, not the id). `recordKey`/`hlc`/`op`/`origin`/`observed` are reserved
 * envelope fields, never store fields.
 */
export declare const EVOLUTION_ACTION_STORE_KNOWN_FIELDS: ReadonlyArray<string>;
/** The tombstone's store-owned fields beyond the reserved envelope set. `deletedAt`
 *  is the only store field a delete carries. */
export declare const EVOLUTION_ACTION_TOMBSTONE_KNOWN_FIELDS: ReadonlyArray<string>;
/** Is `v` a valid ISO-8601 date string (and ONLY a date — no smuggled markup)? A
 *  string Date.parse rejects, or that contains an injection char (`<`, `>`, `"`), is
 *  not a clean ISO date. */
export declare function isIso8601(v: unknown): v is string;
/**
 * The `evolution-action-record` store schema — a DISCRIMINATED UNION on `op`. Strict typed
 * validation on top of the envelope: reject free text beyond the known fields, TYPE-CLAMP
 * every known field (`createdAt`/`dueBy`/`completedAt` ISO-8601-or-absent, `priority`/
 * `status` enum, `tags` string[], `description`/free text length-clamped) so markup cannot
 * smuggle through a render slot that bypasses sanitize(). Returns the validated
 * store-specific object (known fields only), or null to reject the WHOLE record. PURE (no
 * I/O, no mutation of `raw`).
 *
 * The envelope validator has ALREADY validated `op` ∈ {put,delete} before calling this.
 * We branch on it so a tombstone `{recordKey, op:'delete', hlc, origin, deletedAt}` passes
 * (only `deletedAt` is a legal store field for a delete) WITHOUT being marked invalid by
 * the rich VALUE schema.
 */
export declare const evolutionActionRecordStoreSchema: StoreFieldSchema;
/** Normalize a string for the content fingerprint: trim + lowercase + collapse internal
 *  whitespace, so trivial formatting differences across machines do not split the same
 *  action into two records. */
export declare function normalizeForKey(v: string): string;
/**
 * Derive the cross-machine-stable recordKey for an action (fork #1). An action is "the
 * same" across machines by its STABLE CONTENT IDENTITY, NOT by the per-machine,
 * sequentially-assigned `ACT-NNN` id — VM-A and VM-B mint different ACT ids for the same
 * committed action, so an id-keyed record could never collide them (exactly the
 * relationship-UUID / LRN-id trap the prior kinds solved with a stable identity surface).
 *
 * The key is a deterministic, collision-resistant hash:
 *   sha256(normalize(title) + '\x1f' + normalize(commitTo || '') + '\x1f' + createdAt)
 * hex-truncated to 32 chars (the same shape UnionReader.conflictId uses). The `\x1f`
 * (unit separator) is an un-typeable delimiter so two actions cannot collide by straddling
 * the field boundary.
 *
 * `createdAt` is the strong disambiguator: two distinct actions with the same title +
 * commitTo created at different instants never collide. `commitTo` (who the commitment was
 * made to) further distinguishes the same-titled action made to two people. Returns null
 * when title OR createdAt is empty (a degenerate record with no stable identity surface —
 * the caller skips emission; it can never collide a stranger by an empty key).
 *
 * COLLISION SAFETY: two DIFFERENT actions share a key ONLY if they share the EXACT same
 * normalized title AND commitTo AND createdAt — which IS the definition of "the same
 * action". SPLIT-IDENTITY SAFETY: the same action derives the SAME key on both machines IFF
 * both hold the same title/commitTo/createdAt; the normalization absorbs trivial formatting
 * drift. NOTE: status/priority/completedAt are DELIBERATELY excluded from the key — they
 * are the MUTABLE fields (fork #2); keying on them would split the same action into a new
 * record on every status change instead of updating the one record.
 */
export declare function deriveEvolutionActionRecordKey(title: string, commitTo: string | null | undefined, createdAt: string): string | null;
/** The `data` object an `evolution-action-record` journal entry carries. */
export type EvolutionActionRecordData = Record<string, unknown>;
/** Input to buildEvolutionActionRecordData: the record to emit, the freshly-ticked hlc,
 *  this machine's origin id, and the observed-witness (the hlc already merged for THIS
 *  recordKey before writing, or absent). */
export interface BuildEvolutionActionRecordInput {
    record: ActionItem;
    hlc: HlcTimestamp;
    origin: string;
    observed?: HlcTimestamp;
}
/** The named error a record-over-cap surfaces: not silent-truncate, not suspect-wedge. */
export declare class EvolutionActionRecordTooLargeError extends Error {
    readonly recordKey: string;
    readonly bytes: number;
    constructor(recordKey: string, bytes: number);
}
/**
 * Build the disclosure-minimized `evolution-action-record` envelope `data` for an
 * `op:'put'` (fork #1/#2). Emits ONLY the enumerated action projection — NEVER the local
 * `ACT-NNN` id. recordKey = the derived content-fingerprint identity surface (fork #1).
 *
 * Returns null when the record has no stable identity surface (empty title/createdAt ⇒
 * deriveEvolutionActionRecordKey null — the caller skips emission). Throws
 * EvolutionActionRecordTooLargeError when the projection STILL exceeds the 64KB per-entry
 * cap (a NAMED, surfaced rejection — never silent-truncate).
 */
export declare function buildEvolutionActionRecordData(input: BuildEvolutionActionRecordInput): EvolutionActionRecordData | null;
/** Throw EvolutionActionRecordTooLargeError if the projected data serializes over the
 *  per-entry cap. The cap is set so a legal disclosure-minimized record can never reach
 *  it; this is the belt-and-suspenders named rejection. */
export declare function assertProjectionUnderCap(recordKey: string, data: EvolutionActionRecordData): void;
/** Input to buildEvolutionActionTombstoneData: the title/commitTo/createdAt of the removed
 *  action (to derive the recordKey identity surface), the freshly-ticked hlc, the origin,
 *  and the deletedAt timestamp. */
export interface BuildEvolutionActionTombstoneInput {
    title: string;
    commitTo: string | null | undefined;
    createdAt: string;
    hlc: HlcTimestamp;
    origin: string;
    deletedAt: string;
    observed?: HlcTimestamp;
}
/**
 * Build an `op:'delete'` TOMBSTONE `data` for an action queue-REMOVAL. recordKey = the SAME
 * content-fingerprint identity surface the value records key on, so the tombstone reaches
 * the same action's record on every machine even though the local ACT ids differ. Returns
 * null when title/createdAt are empty (no identity surface to tombstone).
 *
 * CRITICAL (fork #2): a `completed`/`cancelled` action is a TERMINAL state, NOT a delete —
 * its record is retained (history). This tombstone fires ONLY when an action is actually
 * REMOVED from the queue (the prune-over-maxActions path), else a peer re-replicates the
 * locally-removed action forever (resurrection). The delete-resurrection guard lives in the
 * merge (a later `delete` hlc wins over an earlier `put`).
 */
export declare function buildEvolutionActionTombstoneData(input: BuildEvolutionActionTombstoneInput): EvolutionActionRecordData | null;
/** A merged action view entry: the projected record fields PLUS its origin machine id (so
 *  a foreign record is rendered inside the untrusted-data envelope). READ-ONLY — NEVER
 *  written back into the local store. */
export interface MergedActionView {
    recordKey: string;
    origin: string;
    /** The validated, type-clamped projection fields (the receive-side schema already ran
     *  on apply; here `data` is that validated portion). */
    data: Record<string, unknown>;
    /** True when this view entry is one of ≥2 concurrent variants of an OPEN conflict
     *  (append-both — both surface as advisory hints; the read NEVER suppresses a usable view
     *  AND NEVER blocks on the unresolved conflict). */
    conflicted: boolean;
}
/**
 * Collapse a `Map<recordKey, UnionResult>` into the merged action view.
 * HIGH-impact-at-replication / ADVISORY-at-read contract (fork #3):
 *   - A resolved single value ⇒ that one view entry.
 *   - An OPEN concurrent conflict ⇒ BOTH (all) `put` variants as separate entries
 *     (append-both — both surface as ADVISORY guidance, e.g. one machine's `completed` and
 *     another's `in_progress`; the read NEVER suppresses a usable view AND NEVER BLOCKS
 *     waiting on operator resolution — an action is a work item to surface, not authority).
 *     A `delete` variant contributes nothing to display.
 *   - A delete-resolved key (every origin's latest is a tombstone) ⇒ nothing (the
 *     delete-resurrection guard: a later delete wins over an earlier put).
 * The read is READ-ONLY: a replicated record NEVER clobbers a divergent local record — the
 * local store files are never written here.
 */
export declare function mergeUnionToActions(union: Map<string, UnionResult>): MergedActionView[];
/**
 * Render a FOREIGN (replicated) action record into a session-context block, wrapped in an
 * explicit `<replicated-untrusted-data origin="…">` envelope so the session model treats it
 * as a PEER'S work item to re-ground against, never a directive. EVERY rendered field is
 * escaped — there is no "trusted because machine-set" slot. A null `data.title` (a
 * malformed view) yields null.
 */
export declare function renderForeignActionContext(view: MergedActionView): string | null;
/**
 * Build an OriginRecord for the OWN actions store (the single-origin materialization the
 * union reader merges against peer replicas). recordKey = derived content-fingerprint
 * identity surface; the envelope carries a SYNTHETIC own-origin HLC stamp derived
 * deterministically from `createdAt` (physical) nudged by the status progression (logical)
 * so the own record has a well-formed, stable position relative to peer records — a later
 * `completed` edit positions after the original `pending` put. Returns null for a degenerate
 * record (no identity surface). The local `ACT-NNN` id is NEVER carried into the replicated
 * namespace.
 */
export declare function evolutionActionToOriginRecord(record: ActionItem, origin: string): OriginRecord | null;
/** The ReplicatedKindRegistry registration for the `evolution-action-record` store.
 *  server.ts registers this onto the shared registry; the dual-registry coupling test
 *  asserts `kind` is also present in JOURNAL_KINDS. */
export declare const EVOLUTION_ACTION_KIND_REGISTRATION: {
    readonly kind: "evolution-action-record";
    readonly store: "evolutionActions";
    readonly schema: StoreFieldSchema;
};
/** Convenience: the store's contributing journal kinds (for rollback-unmerge's
 *  kindsForStore('evolutionActions') wiring). */
export declare function evolutionActionContributingKinds(): string[];
/** The store's impact tier resolver, for ReplicatedStoreReader.tierOf. Returns HIGH for the
 *  `evolutionActions` store (and HIGH for any unknown store — the conservative
 *  append-both-and-flag direction, never a silent clobber). */
export declare function evolutionActionTierOf(_store: string): ImpactTier;
/** Re-export the envelope type for callers building/applying evolution-action-record
 *  envelopes. */
export type { ReplicatedEnvelope };
//# sourceMappingURL=EvolutionActionsReplicatedStore.d.ts.map