/**
 * Wizard state machine — backbone of the conversational setup flow.
 *
 * This is the deterministic spine. Each state has a `prompt` (what the
 * user is asked), a list of `choices` (when multi-choice) or `kind:
 * 'text'` (free-text), and `nextState` derived from the user's answer.
 * Side-effects (init, user add, server start, etc.) are emitted as
 * `actions` the driver runs at appropriate transitions.
 *
 * Framework-specific drivers (codex-driver.ts) consume this state
 * machine. The framework's LLM is invoked ONLY to generate narrative
 * intro text for each state — not to drive transitions. Transitions
 * are owned by instar.
 *
 * This is the "Structure > Willpower" answer to the v1.2.11 failure
 * mode where Codex ignored the wizard SKILL.md's conversational
 * contract and executed the entire setup non-interactively. With the
 * state machine owning the flow, the framework cannot get out of hand
 * — each per-turn LLM call has a single bounded text job.
 */
export type Autonomy = 'guided' | 'proactive' | 'autonomous';
export type Messaging = 'telegram' | 'whatsapp' | 'slack' | 'skip';
export interface WizardAnswers {
    agentName?: string;
    agentRole?: string;
    userName?: string;
    autonomy?: Autonomy;
    messaging?: Messaging;
    telegramConfigured?: boolean;
    whatsappConfigured?: boolean;
    slackConfigured?: boolean;
    githubBackupRepo?: string;
    serverStarted?: boolean;
}
export type WizardActionKind = 'init' | 'add-user' | 'setup-telegram-agentic' | 'setup-whatsapp-agentic' | 'setup-slack-agentic' | 'github-backup' | 'start-server' | 'install-autostart' | 'send-greeting';
export interface WizardAction {
    kind: WizardActionKind;
    description: string;
}
export type StateKind = 'narrative-then-prompt' | 'action' | 'terminal';
export interface NarrativeState {
    id: string;
    kind: 'narrative-then-prompt';
    /**
     * The question text the user sees. Framework drivers should NOT
     * regenerate this — it is the structural prompt, displayed verbatim.
     * Narrative intro text is rendered separately by the driver via a
     * per-turn LLM call.
     */
    prompt: string;
    /** Optional preamble keys for the driver to look up narrative-prompt builders. */
    narrativeContext: string;
    input: {
        kind: 'text';
        placeholder?: string;
        required?: boolean;
    } | {
        kind: 'choice';
        choices: Array<{
            value: string;
            label: string;
        }>;
    };
    /**
     * Validate the user's raw answer BEFORE the driver routes it through
     * `next`. Return `null` to accept; return a friendly message to
     * surface to the user and re-render the same state. This is how
     * the wizard catches buffered-Enter empty submissions on required
     * fields and unmatched choice inputs — surfaces an "I think
     * something slipped through, try again" reprompt instead of
     * silently defaulting.
     */
    validate?: (answer: string) => string | null;
    /** Where to go next based on the user's answer. Driver invokes this. */
    next: (answer: string, answers: WizardAnswers) => {
        state: string;
        updates: Partial<WizardAnswers>;
    };
}
export interface ActionState {
    id: string;
    kind: 'action';
    action: WizardAction;
    /**
     * Where to go after the action completes. Drivers are responsible
     * for running the action and applying any answer updates.
     */
    next: (answers: WizardAnswers) => string;
}
export interface TerminalState {
    id: string;
    kind: 'terminal';
    /** Final farewell text. */
    farewell: string;
}
export type WizardState = NarrativeState | ActionState | TerminalState;
/**
 * Normalize a user-typed answer for choice matching: accepts the
 * 1-based numeric index OR the choice's `value` (case-insensitive
 * prefix-match against the label).
 */
export declare function resolveChoice(answer: string, choices: Array<{
    value: string;
    label: string;
}>): string | null;
/**
 * Standard validator: require non-empty trimmed text. Surfaces a
 * friendly reprompt when the user submits whitespace-only (the
 * classic buffered-Enter problem).
 */
export declare function requireNonEmpty(fieldLabel: string): (answer: string) => string | null;
/**
 * Standard validator for a choice prompt: surfaces a friendly retry
 * when the user's input matches none of the offered choices (by
 * number, value, or label prefix).
 */
export declare function requireChoice(choices: Array<{
    value: string;
    label: string;
}>): (answer: string) => string | null;
/**
 * Build the wizard state machine for a fresh project-bound install
 * (the most common entry point — and the one observed broken in the
 * v1.2.11 instar-codey log). Restore / multi-user / multi-machine
 * scenarios are out of scope for the first hybrid-wizard PR; they
 * stay on the existing SKILL.md path until ported.
 */
export declare function buildFreshProjectInstall(): Record<string, WizardState>;
export declare const INITIAL_STATE = "welcome";
//# sourceMappingURL=state-machine.d.ts.map