import type { CiSecretSetupAdvice, CiSecretTarget } from '../ci-secrets.js';
import type { IosEffectDeps } from '../ios/flow.js';
import type { TailEffectDeps } from '../tail/flow.js';
import type { OnboardingStep } from '../types.js';
import type { Platform } from './contract.js';
/**
 * The iOS driver-held transient state — the exact `IosEffectDeps['carried']`
 * shape, plus the MCP-only `parkedImportStep` (S12): the interactive import
 * sub-flow prompt the driver parked between tool calls — the headless mirror
 * of the TUI's React `step` state for the EPHEMERAL import prompts, which
 * resume routing can never reproduce (see engine.ts iosParkedStep). NON-SECRET
 * (a step name). Wiped with the session; a restart self-heals via a fresh
 * import-scanning that re-derives the inventory and re-renders the picker.
 */
export type IosCarried = NonNullable<IosEffectDeps['carried']> & {
    parkedImportStep?: OnboardingStep;
    /**
     * The chosen identity's Apple cert resource id (import-checking-apple-cert's
     * transient — typed on IosStepCtx, not on the engine's carried shape). The
     * registry really holds it after the transient merge; typing it here lets
     * the driver DROP it when the user re-picks a different identity (the TUI
     * clears its appleCertId mirror the same way). NON-SECRET (an Apple id).
     */
    _appleCertIdForChosen?: string;
};
/**
 * The tail driver-held transient state — the exact `TailEffectDeps['carried']`
 * shape, plus the NON-SECRET tail OUTCOME facts the outcome-aware terminal
 * summary harvests (engine.ts harvestTailOutcomes → tailCompleteResult): the
 * exact upload summary line (counts/labels only), the written workflow path
 * and the exported .env path. These three are non-secret BY CONSTRUCTION and
 * are the one carried subset allowed to surface verbatim in a tool result —
 * secret VALUES (savedCredentials / ciSecretEntries) must still never leave
 * this registry.
 */
export type TailCarried = NonNullable<TailEffectDeps['carried']> & {
    ciSecretUploadSummary?: string;
    workflowFilePath?: string;
    envExportPath?: string;
};
/**
 * S9-S11: the MCP's parked interactive TAIL step + the NON-SECRET view context
 * it was rendered with (option inventories / labels — never credential values).
 * The TUI holds the current tail step in React state; the MCP mirrors it here so
 * (a) the strict tail gate validates an answer against the step that actually
 * asked, and (b) a re-render (corrective message, plain re-check) re-asks the
 * SAME parked question instead of drifting forward through the resume router —
 * which would collapse past consent gates like preview-workflow-file. A server
 * restart loses the park; resume routing then takes over (the frozen
 * tailResumeStep contract). EXPLICITLY NO SECRETS: ciSecretEntries (values)
 * stay in tailCarried; only derived key NAMES may surface in tool results.
 */
export interface TailParkedState {
    step: string;
    ciSecretTargets?: CiSecretTarget[];
    ciSecretSetupAdvice?: CiSecretSetupAdvice[];
    ciSecretRepoLabel?: string | null;
    ciSecretError?: string;
    availableScripts?: Record<string, string>;
    recommendedScript?: string | null;
}
export interface OnboardingSessionState {
    iosCarried: IosCarried;
    tailCarried: TailCarried;
    tailParked?: TailParkedState;
    /**
     * The platform this session is setting up, as CHOSEN by the user (platform
     * picker answer / single-platform auto-route / explicit `{ platform }`), NOT
     * inferred from on-disk progress. This is what lets a bare `next_step({})`
     * resume the right platform AND lets two concurrent server processes onboard
     * the same app for different platforms without reading each other's progress
     * files. Process-local: a restart loses it and the flow re-asks the picker.
     */
    activePlatform?: Platform;
    /**
     * The platform whose continue-vs-restart resume prompt has already been
     * resolved THIS session — shown and answered, or skipped as unnecessary (no
     * resumable on-disk progress). While it differs from the committed platform, a
     * fresh platform entry first shows the resume prompt (mirroring the TUI's
     * `resume-prompt` fork) instead of silently resuming. Process-local: a restart
     * loses it and the prompt is re-offered. Reset by runStart so a fresh "start
     * onboarding" always re-asks.
     */
    resumeResolvedFor?: Platform;
}
/**
 * Get the session state for `appId`, creating an empty one on demand.
 * The returned object is the current SNAPSHOT: merges replace the carried
 * objects rather than mutating them, so re-read after merging.
 */
export declare function getSession(appId: string): OnboardingSessionState;
/**
 * Read the platform this session committed to (via setSessionPlatform), or
 * undefined when none has been chosen yet (fresh session, or after a restart).
 * Deliberately does NOT consult disk progress — the platform is a session
 * decision, not a property of what happens to be saved on disk.
 */
export declare function getSessionPlatform(appId: string): Platform | undefined;
/**
 * Record (or, with `undefined`, clear) the platform this session is setting up.
 * Called when the user picks at the platform gate, when a single-platform
 * project auto-routes, or on any explicit `{ platform }`. Cleared by runStart so
 * a fresh "start onboarding" always re-asks instead of silently resuming.
 */
export declare function setSessionPlatform(appId: string, platform: Platform | undefined): void;
/**
 * Read which platform's resume prompt has already been resolved this session
 * (shown+answered, or determined unnecessary), or undefined when none has.
 * Process-local; deliberately ignores disk — the resume decision is a session
 * decision, exactly like the platform itself.
 */
export declare function getResumeResolvedFor(appId: string): Platform | undefined;
/**
 * Record (or, with `undefined`, clear) which platform's continue-vs-restart
 * resume prompt has been resolved this session. Set once the prompt is answered
 * or skipped as unnecessary; cleared by runStart so a fresh start re-asks.
 */
export declare function setResumeResolvedFor(appId: string, platform: Platform | undefined): void;
/**
 * Drop the per-flow carried transients (iOS carried, tail carried, tail park)
 * for `appId` while PRESERVING the session-level decisions (activePlatform,
 * resumeResolvedFor). Used by the resume prompt's "restart" arm: the on-disk
 * progress is wiped, so the in-memory carried state from the old run must go
 * too — but the session stays committed to the same platform and must not
 * re-ask the resume prompt it just answered. Immutable: builds a NEW entry.
 */
export declare function clearSessionCarried(appId: string): void;
/**
 * Merge `partial` into the iOS carried state for `appId` and return the new
 * merged carried object. `undefined` values leave the prior value intact.
 */
export declare function mergeIosCarried(appId: string, partial: Partial<IosCarried>): IosCarried;
/**
 * Merge `partial` into the tail carried state for `appId` and return the new
 * merged carried object. `undefined` values leave the prior value intact.
 */
export declare function mergeTailCarried(appId: string, partial: Partial<TailCarried>): TailCarried;
/**
 * Park the current interactive tail step (+ its non-secret view context) for
 * `appId`. REPLACES any prior park — each render re-parks the step it shows,
 * so the park always mirrors the question currently in front of the user.
 * Immutable: builds a NEW session entry; prior snapshots are untouched.
 */
export declare function setTailParked(appId: string, parked: TailParkedState): void;
/**
 * Drop `keys` from the iOS carried state for `appId` and return the new
 * carried object. The complement of mergeIosCarried for one-shot consumable
 * fields (e.g. the verify-app `verifyAction` pick, which the driver MUST clear
 * after the resolver effect ran so a later re-entry runs the initial fetch —
 * merge semantics skip `undefined`, so a merge can never clear). Immutable:
 * builds a NEW carried object; prior snapshots are untouched.
 */
export declare function dropIosCarried(appId: string, keys: (keyof IosCarried)[]): IosCarried;
/**
 * Drop the session entry for `appId`. Idempotent: safe on an absent appId and
 * safe to call twice. The next getSession() recreates a fresh empty session.
 */
export declare function clearSession(appId: string): void;
/** Drop every session (test isolation only — production code clears per appId). */
export declare function clearAllSessions(): void;
