/**
 * Mesh contract v2 — first-class identity, scopes, and protocol version.
 *
 * Replaces the implicit conventions that grew across mesh-events.ts,
 * mesh-work-queue.ts, mesh-ledger.ts, and mesh-tools.ts where the same
 * concept (a coordinator, a session, a task status) appeared in different
 * shapes per file. The audit found:
 *
 *   - PendingMeshCoordinatorEvent had no targetCoordinatorDaemonId. All
 *     events were broadcast to every coordinator that drained them. Two
 *     coordinators sharing a mesh would each receive every event,
 *     leading to duplicate completion handling and missed targeting.
 *   - drainPendingMeshCoordinatorEvents accepted only meshId. The caller's
 *     coordinator identity was never available, so per-coordinator
 *     routing was impossible by construction.
 *   - Session identifier keys diverged across stores: targetSessionId /
 *     assignedSessionId / instanceId / runtimeSessionId / providerSessionId.
 *     resolveEventSessionId() tried four fallbacks per call.
 *   - No protocol version on the JSONL ledger or MeshRuntimeStore. Schema
 *     evolutions had no guard rail.
 *   - mesh_reconcile_ledger existed as a routine recovery tool, not as
 *     an incident-response escape hatch. That itself signals the routing
 *     layer cannot be trusted.
 *
 * This module introduces the types; the actual wiring lands in B2 (data
 * model + 3-way transactional store), B3 (MCP layer enforcement), and B4
 * (frontend consumption). B1 is intentionally non-breaking — it adds the
 * types and leaves runtime behaviour unchanged.
 */
/** Provider type identifier (e.g. 'claude-cli', 'codex-cli', 'roo-code').
 *  Free-form string; no shared enum exists in daemon-core yet. */
type ProviderType = string;
export declare const MESH_PROTOCOL_VERSION_V1: "1.0";
export declare const MESH_PROTOCOL_VERSION_V2: "2.0";
export type MeshProtocolVersion = typeof MESH_PROTOCOL_VERSION_V1 | typeof MESH_PROTOCOL_VERSION_V2;
export declare const SUPPORTED_MESH_PROTOCOL_VERSIONS: readonly MeshProtocolVersion[];
export declare function isSupportedMeshProtocolVersion(value: unknown): value is MeshProtocolVersion;
/**
 * Identity of a mesh coordinator. Required (non-optional) on every dispatch
 * and drain operation in v2 — opaque/missing identity is the audit's
 * smoking gun for routing failures and is structurally banned by the v2
 * types.
 *
 * - daemonId: the machineId of the daemon hosting the coordinator. Stable
 *   across coordinator restarts on the same machine.
 * - coordinatorRunId: a UUID generated when the coordinator process starts.
 *   Stable for the coordinator's lifetime, fresh on restart. Required so
 *   two coordinators on the same daemon (one CLI, one MCP) can be told
 *   apart without conflating their drains.
 * - sessionId: optional CLI coordinator session identifier (instanceId).
 *   Present when the coordinator is itself a CLI session, absent for
 *   pure MCP coordinators.
 */
export interface CoordinatorIdentity {
    readonly daemonId: string;
    readonly coordinatorRunId: string;
    readonly sessionId?: string;
}
export declare function coordinatorIdentityEquals(a: CoordinatorIdentity, b: CoordinatorIdentity): boolean;
export declare function coordinatorIdentityKey(identity: CoordinatorIdentity): string;
/**
 * Unified mesh session identifier. v1 referred to "the session" with five
 * different field names depending on which store you were reading; v2
 * collapses them into one explicit handle that carries every disambiguator
 * a consumer might need.
 *
 * - nodeId: the mesh node this session belongs to (FK into mesh node table).
 * - sessionId: provider-instance identifier (the runtime session id).
 * - providerType: which provider category/type the session runs (e.g.
 *   'claude-cli', 'codex-cli', 'roo-code').
 * - coordinatorDaemonId: which coordinator dispatched the work that
 *   spawned this session. Used for completion event routing.
 * - assignedAt: ms epoch when the session was bound to its current task.
 */
export interface MeshSessionHandle {
    readonly nodeId: string;
    readonly sessionId: string;
    readonly providerType: ProviderType;
    readonly coordinatorDaemonId: string;
    readonly assignedAt: number;
}
export declare function meshSessionHandleKey(handle: MeshSessionHandle): string;
/**
 * Single canonical task status enum. v1 had at least three overlapping
 * sets (queue / ledger / direct-dispatch). v2 consumers import from here.
 */
export declare const MESH_TASK_STATUSES: readonly ["pending", "assigned", "in_progress", "completed", "failed", "cancelled"];
export type MeshTaskStatus = typeof MESH_TASK_STATUSES[number];
export declare function isMeshTaskStatus(value: unknown): value is MeshTaskStatus;
/**
 * Explicit scope for pending coordinator events. v1 had no scope: every
 * event was broadcast to every drainer. v2 forces producers to declare
 * intent.
 *
 * - 'unicast': delivered to exactly one coordinator (intendedFor). Other
 *   coordinators' drains skip it.
 * - 'broadcast': delivered to every coordinator on the mesh. Used for
 *   system-wide signals (e.g. mesh-wide policy changes). The v1 default
 *   becomes explicit here so audit tools can flag unintended broadcasts.
 * - 'system': delivered to the daemon-level handler, not coordinators.
 *   Reserved for infrastructure events that no coordinator should see
 *   (e.g. ledger reconciliation outcomes).
 */
export declare const MESH_EVENT_SCOPES: readonly ["unicast", "broadcast", "system"];
export type MeshEventScope = typeof MESH_EVENT_SCOPES[number];
export declare function isMeshEventScope(value: unknown): value is MeshEventScope;
/**
 * v2 shape of a pending coordinator event. Strict supersets of the v1
 * shape — every v1 field is preserved so existing readers do not break;
 * v2 fields (scope, dispatchedBy, intendedFor, protocolVersion) are
 * additive and consulted by v2-aware drainers only.
 *
 * Mixed v1/v2 events coexist during the rollout window. B2 fully cuts
 * over once every coordinator drain is v2-aware.
 */
export interface PendingMeshCoordinatorEventV2 {
    readonly event: string;
    readonly meshId: string;
    readonly nodeLabel: string;
    readonly nodeId?: string;
    readonly workspace?: string;
    readonly metadataEvent: Record<string, unknown>;
    readonly coordinatorMessage?: string;
    readonly queuedAt: number;
    readonly protocolVersion: MeshProtocolVersion;
    /**
     * Idempotency key. A UUID generated ONCE at emit time and preserved verbatim
     * across every store (SQLite payload + column, JSONL) and the P2P relay
     * boundary. The receiving drain uses eventId as the authoritative dedup key
     * (B3): an event whose eventId was already drained is skipped even if its
     * content fingerprint differs. Distinct from the content fingerprint, which
     * stays the v1 dedup mechanism during rollout.
     */
    readonly eventId: string;
    readonly scope: MeshEventScope;
    readonly dispatchedBy: CoordinatorIdentity;
    /**
     * Required when scope === 'unicast', forbidden otherwise. Drainers MUST
     * skip unicast events whose intendedFor does not equal their own identity.
     */
    readonly intendedFor?: CoordinatorIdentity;
}
/**
 * v2 ledger entry additions. The originatingCoordinator field is the
 * source of truth that lets completion events route back to the
 * coordinator that dispatched the task. v1's "worker settings carried it
 * if it happened to be set" approach is replaced.
 */
export interface MeshLedgerOriginatingCoordinatorV2 {
    readonly originatingCoordinator: CoordinatorIdentity;
    readonly protocolVersion: MeshProtocolVersion;
}
export declare class MeshContractViolationError extends Error {
    readonly violationPath: string;
    readonly protocolVersion: MeshProtocolVersion;
    constructor(protocolVersion: MeshProtocolVersion, violationPath: string, detail: string);
}
export declare function assertCoordinatorIdentity(raw: unknown, path: string): CoordinatorIdentity;
export declare function assertPendingMeshCoordinatorEventV2(raw: unknown, path?: string): PendingMeshCoordinatorEventV2;
/**
 * Decide whether a v2 pending event should be delivered to the given drainer.
 * Centralised so every drain implementation uses the same rule.
 *
 *   - 'broadcast': always delivered. NOTE: a terminal task event that reached the
 *     queue as broadcast is an ownership leak (it belongs to its dispatching
 *     coordinator). This pure helper does not have the drain-window
 *     daemon-form/session matching semantics, so the terminal+broadcast
 *     dispatchedBy filter is applied one layer up in the drainer (see
 *     mesh-events-pending routeV2EventsForDrainer) where those semantics live.
 *   - 'system': never delivered to coordinators (system handler only).
 *   - 'unicast': delivered iff intendedFor matches drainer identity.
 *
 * v1 events (no scope / no protocolVersion) are treated as broadcast for
 * backward compatibility during rollout; B3 tightens this so v1 events
 * are quarantined to a dedicated drain endpoint instead.
 */
export declare function shouldDeliverPendingEventToCoordinator(event: PendingMeshCoordinatorEventV2, drainer: CoordinatorIdentity): boolean;
/**
 * True for a terminal task event (completion / stop / refine outcome). A terminal
 * event belongs to exactly the coordinator that dispatched the task, so it must
 * never fan out to sibling coordinators that did not dispatch it. Used by the
 * emit-side stamp (to avoid downgrading an unaddressed terminal event to full
 * broadcast) and by the drain-side filter (defense-in-depth for any terminal
 * event that already reached the queue as broadcast).
 */
export declare function isTerminalTaskEvent(eventName: string): boolean;
/**
 * Default the v2 scope for an event by its producer event name (design decision
 * §3). Terminal task events and coordinator-addressed alerts → unicast (routed
 * to the originating coordinator). Everything else — node lifecycle and
 * progress signals — → broadcast, which also matches v1's implicit "deliver to
 * any coordinator" behaviour, so an unstamped v1 event and a v2-stamped-as-
 * broadcast event route identically during rollout. No event currently defaults
 * to 'system'; the scope remains in MESH_EVENT_SCOPES for wire compatibility
 * (an already-queued or version-skewed 'system' event still routes away from
 * coordinators).
 */
export declare function defaultScopeForEvent(eventName: string): MeshEventScope;
/**
 * The v2 envelope stamp applied to a pending coordinator event at emit time.
 * Additive over the v1 shape: every field is consulted by v2-aware drainers
 * only, so a v1 reader that ignores them is unaffected.
 */
export interface PendingEventEmitStampV2 {
    readonly protocolVersion: typeof MESH_PROTOCOL_VERSION_V2;
    readonly eventId: string;
    readonly scope: MeshEventScope;
    readonly dispatchedBy: CoordinatorIdentity;
    readonly intendedFor?: CoordinatorIdentity;
}
/**
 * Build a coordinator identity from the loosely-typed fields the v1 emit call
 * sites already carry (a daemonId, and — sometimes — a coordinator session id).
 * Returns undefined when no usable daemonId is present; the caller then leaves
 * the event unstamped (v1, broadcast-treated) rather than fabricating identity.
 * coordinatorRunId is not known at every emit site yet (B2 wires the registry),
 * so it falls back to the daemonId — a stable, non-empty value that keeps the
 * identity well-formed for assertCoordinatorIdentity without inventing a UUID
 * that would differ per emit and defeat equality.
 */
export declare function coordinatorIdentityFromEmitFields(fields: {
    daemonId?: string | null;
    coordinatorRunId?: string | null;
    sessionId?: string | null;
}): CoordinatorIdentity | undefined;
/**
 * Compute the v2 emit stamp for an event (B2a). `eventId` MUST be supplied by
 * the caller (generated via crypto.randomUUID at the daemon-core boundary so
 * this module stays dependency-free and deterministically testable). Scope
 * defaults from the event name unless explicitly overridden.
 *
 * When `dispatchedBy` cannot be constructed (no coordinator daemon known),
 * returns undefined: the event stays a v1 (unstamped) event and is broadcast-
 * treated during rollout, exactly as before — no regression, no fabricated
 * identity. When the resolved scope is 'unicast' but no `intendedFor` is
 * available, the fallback depends on the event class:
 *
 *   - Terminal task events (completion / stop / refine outcome) MUST NOT be
 *     broadcast to every coordinator — a completion belongs to the coordinator
 *     that dispatched the task, and broadcasting it makes non-owner coordinators
 *     (e.g. sibling MAGI coordinators that never dispatched this replica's task)
 *     act on a completion that is not theirs (MAGI-REPLICA-COMPLETION-EVENT-LEAK).
 *     For these we address the event to `dispatchedBy` (the dispatching
 *     coordinator) and KEEP it unicast, so the stamp stays contract-valid and the
 *     event reaches only its originating coordinator.
 *   - Any other unicast event with no addressable target falls back to broadcast
 *     (contract-valid, still delivered, never dropped) — unchanged.
 */
export declare function buildPendingEventEmitStamp(opts: {
    eventName: string;
    eventId: string;
    dispatchedBy?: CoordinatorIdentity;
    intendedFor?: CoordinatorIdentity;
    scope?: MeshEventScope;
}): PendingEventEmitStampV2 | undefined;
export {};
