/**
 * # bus/plan-instances — group a bus's PLAN stream into exact Plan INSTANCES (kestrel-22j.15)
 *
 * A pure, deterministic fold of a bus's {@link PlanEvent}s into the distinct Plan **instances** they trace —
 * the ONE place both report projections (`project(bus)` in {@link ../blotter/project.ts} and `buildReport`
 * in {@link ../session/sim.ts}) agree on "what is one instance", so their groupings can never drift.
 *
 * ## Why a name is not an instance (the P0 this fixes)
 * A plan NAME is a **Lineage** key (names-are-data, ADR-0006): `fade-ladder` authored fresh on 40 days is one
 * strategy with 40 instances, and a name may legally RECUR after an earlier instance is `done` (the F4
 * same-name-supersession guard in {@link ../engine/plans.ts} only forbids re-declaring a name still owned by a
 * NOT-done plan). Grouping the PLAN stream by name ALONE therefore merges a `done` instance and its same-name
 * replacement into one trace whose terminal outcome is the last one seen — silently erasing the predecessor's
 * (kestrel-22j.15). Grouping by INSTANCE keeps them apart; Lineage aggregation (by name) is a SEPARATE roll-up
 * a consumer does over `group.plan`.
 *
 * ## The instance key (v5 explicit, else an explicit pre-v5 migration)
 * - **v5 bus** — every PLAN event carries {@link PlanEvent.plan_instance}, the id the engine minted
 *   deterministically at registration. The key IS that id: exact, no inference.
 * - **pre-v5 bus** (no `plan_instance`) — MIGRATE EXPLICITLY by **lifecycle sessionization**: a name's next
 *   instance opens at the structural boundary where its currently-open instance has already reached a terminal
 *   `done`. This is exact — never a timestamp heuristic, never fuzzy name-matching — because F4 guarantees a
 *   name only recurs after its predecessor is `done`, so a `done`→next-event boundary is precisely one
 *   instance boundary. Fail-closed doctrine (RUNTIME §8): a pre-v5 bus is migrated, never silently
 *   mis-identified.
 *
 * A single bus is all-or-nothing (an engine either stamps every plan event with an id or, pre-v5, none), so the
 * two paths never interleave within one bus.
 *
 * Determinism (RUNTIME §0): pure function of the bus bytes — no wall clock, no RNG. Output order is
 * `(name asc, first-seq asc)`, which reproduces the prior name-sorted order exactly when every name has a
 * single instance, and orders same-name instances by first appearance.
 */
import type { BusEvent, PlanEvent } from "./types.ts";
/** One exact Plan instance traced off the bus: its Lineage name, its instance identity (the explicit
 * `plan_instance` on a v5 bus, else a deterministic sessionized key), and its PLAN events in seq order. */
export interface PlanInstanceGroup {
    /** The authored plan NAME — the Lineage aggregation key (a consumer rolls instances up BY this). */
    readonly plan: string;
    /** The exact instance identity: {@link PlanEvent.plan_instance} (v5) or a sessionized migration key (pre-v5). */
    readonly instance: string;
    /** This instance's PLAN events, in bus seq order (lifecycle transitions + any reject notices). */
    readonly events: readonly PlanEvent[];
}
/**
 * Group a bus's PLAN events into the distinct Plan instances they trace (see the module header). Pure and
 * deterministic. Non-PLAN events are ignored. The bus is expected in seq order (as every well-formed bus is);
 * events are folded in the order given.
 */
export declare function groupPlanInstances(bus: readonly BusEvent[]): PlanInstanceGroup[];
//# sourceMappingURL=plan-instances.d.ts.map