import type { AgentManager, AgentProcess, EffortLevel } from './agents.js';
import { type ForEachSpec, type ForEachTeammate } from '../workflows.js';
/**
 * Parse a producer's stdout into the item list `expandForEach` fans out over.
 *
 * Two shapes are accepted (issue #343), tried in order:
 *   1. A JSON array — `["a","b","c"]` (each element coerced to a trimmed string).
 *   2. Newline-delimited — one item per line.
 *
 * Empty lines / entries are dropped so a trailing newline or a `[]` never
 * fabricates a phantom teammate. Pure and deterministic — no I/O.
 */
export declare function parseProducedItems(stdout: string): string[];
export interface ProduceItemsOptions {
    /** Working directory for the producer command. */
    cwd?: string | null;
    /** Environment for the producer command (defaults to the current process env). */
    env?: NodeJS.ProcessEnv;
    /** Kill the producer after this many ms (default 120_000). */
    timeoutMs?: number;
    /**
     * Resolve an `itemsRef` (`${step}`-style reference) to a prior step's produced
     * list. When a spec carries `itemsRef` and this resolver returns a list, the
     * producer command is skipped entirely.
     */
    resolveItemsRef?: (ref: string) => string[] | undefined;
}
/**
 * Resolve a `for_each` spec's item list at runtime (issue #343): either by
 * running its `produce:` shell command and parsing stdout, or by resolving an
 * `itemsRef` to a prior step's list. The resulting items feed `expandForEach` /
 * `runForEach`.
 *
 * `itemsRef` wins when a resolver is supplied and returns a list; otherwise the
 * `produce` command runs. A spec with neither a resolvable ref nor a produce
 * command is a hard error — there is nothing to fan out over.
 */
export declare function produceItems(spec: ForEachSpec, opts?: ProduceItemsOptions): Promise<string[]>;
/**
 * Evaluate a verify panel's `keep_if` gate against its boolean votes (issue
 * #343). A `true` vote is a skeptic confirming the finding should be kept.
 *
 *   - `all`      — every skeptic must vote keep.
 *   - `any`      — at least one skeptic votes keep.
 *   - `majority` — strictly more than half vote keep (a tie does NOT pass).
 *
 * An empty panel returns false: with no votes there is nothing affirming the
 * item, so the conservative gate drops it.
 */
export declare function evaluateKeepIf(votes: boolean[], keepIf: 'majority' | 'all' | 'any'): boolean;
/** Per-item verdict after tallying its verify panel. */
export interface ForEachItemVerdict {
    /** The produced item this verdict is for. */
    item: string;
    /** Zero-based index in the (capped) produced list. */
    itemIndex: number;
    /** The stage teammate that handled this item. */
    stageName: string;
    /** Whether the item survives its `keep_if` gate (true when it has no panel). */
    kept: boolean;
    /** The votes that were tallied (empty when the item has no verify panel). */
    votes: boolean[];
    /** The gate applied (undefined when the item has no verify panel). */
    keepIf?: 'majority' | 'all' | 'any';
}
/**
 * Tally the verify panels of an expanded `for_each` and gate each item (issue
 * #343). Groups verify teammates by the stage teammate they depend on, reads a
 * boolean vote per verify teammate via `readVote`, and applies `keep_if`.
 *
 * An item with no verify panel is kept unconditionally (there is no gate).
 * Pure and deterministic: `readVote` is the only place runtime state enters, so
 * this is unit-testable with a synthetic vote reader.
 */
export declare function tallyForEach(teammates: ForEachTeammate[], readVote: (verify: ForEachTeammate) => boolean): ForEachItemVerdict[];
export interface RunForEachOptions {
    /** Working directory for the spawned teammates. */
    cwd?: string | null;
    /**
     * Name of the producer teammate the stage teammates should depend on. When
     * set, each stage runs `--after` the producer so it can't start before the
     * list is available.
     */
    producerName?: string;
    /** Default effort for spawned teammates (per-item overrides live in the spec). */
    effort?: EffortLevel;
    /** Concurrency cap for the wave; falls back to the spec's `concurrency`. */
    concurrency?: number;
}
export interface RunForEachResult {
    /** The expanded descriptors (stage + verify), in spawn order. */
    teammates: ForEachTeammate[];
    /** The AgentProcess handles returned by `spawn`, aligned to `teammates`. */
    spawned: AgentProcess[];
    /** Items the producer emitted (pre-cap). */
    producedCount: number;
    /** Items actually fanned out (post-cap). */
    usedCount: number;
    /** How many items the runaway guard dropped. */
    truncated: number;
}
/**
 * Expand a `for_each` spec against a producer's output and stage every
 * resulting teammate into the given team via the dynamic-add path.
 *
 * Returns the descriptors and the spawned handles so a caller can drive the
 * supervisor and later gather results (e.g. to evaluate a `verify` panel's
 * `keep_if` gate — that vote-counting lives downstream, not here).
 */
export declare function runForEach(mgr: AgentManager, teamName: string, spec: ForEachSpec, items: string[], opts?: RunForEachOptions): Promise<RunForEachResult>;
