/**
 * Shared pure helpers for scenario rules: lifecycle-path parsing and
 * create-payload synthesis. No filesystem / network / mutable state.
 */
import type { ModelInfo, NormalizedSpec } from '../ui-contracts/test-case-types.js';
export interface LifecyclePath {
    /** The lifecycle field on the model (e.g. 'status'). */
    field: string;
    /** Ordered states. */
    states: string[];
    /** Declared transitions. */
    transitions: Array<{
        from: string;
        to: string;
    }>;
    /** Initial state. */
    initial: string;
}
/**
 * Parse a model's `lifecycles:` block into one LifecyclePath per
 * declared lifecycle. Handles both the shorthand flow form
 * (`flow: "draft -> open -> closed"`) and the structured form
 * (`states: [...]`, `transitions: { name: {from,to} } | [{from,to}]`).
 */
export declare function parseLifecyclePaths(model: ModelInfo): LifecyclePath[];
/**
 * Find an undeclared single-hop transition from the initial state — a
 * jump the lifecycle does NOT permit — to drive the negative arm of the
 * walkable rule. Returns null if every other state is directly reachable
 * (e.g. a 2-state lifecycle has no undeclared jump to test).
 */
export declare function findUndeclaredJump(path: LifecyclePath): {
    from: string;
    to: string;
} | null;
/**
 * Build a create payload for a TOP-LEVEL model (no required belongsTo):
 * required business fields + every lifecycle field in its initial state.
 * Returns null if the model needs a parent seeded first (out of v1 scope).
 */
export declare function buildTopLevelPayload(model: ModelInfo, marker: string): Record<string, unknown> | null;
/**
 * Build a create payload for a CHILD model, overlaying foreign-key values
 * (e.g. `{ pollId: '$expr:p.id' }`). Unlike buildTopLevelPayload it does
 * not bail on belongsTo — the caller supplies the parent ids.
 */
export declare function buildChildPayload(model: ModelInfo, marker: string, fkValues: Record<string, unknown>): Record<string, unknown>;
/** The FK column a belongsTo relationship maps to (e.g. `poll` → `pollId`). */
export declare function belongsToFk(relName: string): string;
/**
 * Whether a CURVED op is available on the controller for a model. Mirrors
 * realize: a model controller with an explicit `cured:` block exposes only
 * the listed ops; one with no explicit block gets the full inferred CURVED
 * set. Returns false if no controller owns the model (no API surface).
 */
export declare function opAvailable(spec: NormalizedSpec, modelName: string, op: string): boolean;
//# sourceMappingURL=_shared.d.ts.map