/** * Coverage Gate — Recursive Refinement Loop for Network-AI * * Prevents the system from finishing with incomplete data by acting as a * gatekeeper before the `submit_final` action is allowed. An evaluator LLM * scores the current Blackboard state against the original user goal and * produces a gap list. If the score is below the configured threshold the * orchestrator feeds the gaps back into GoalDecomposer to generate new * sub-tasks. Execution only reaches the COMPLETE state when the score * clears the threshold (or the maximum refinement count is reached). * * The EVALUATING FSM state (added to WORKFLOW_STATES) signals that a * refinement loop is in progress. * * Zero external dependencies — the evaluator function is pluggable. * * @module CoverageGate * @version 1.0.0 */ /** Output from a coverage evaluation call. */ export interface CoverageResult { /** 0–100 completeness score. */ score: number; /** List of topics / questions the current state does NOT yet cover. */ gaps: string[]; /** Human-readable evaluation summary. */ summary: string; /** When the evaluation was completed (epoch ms). */ evaluatedAt: number; } /** * A function that evaluates the current blackboard state against the original * goal and returns a CoverageResult. * * Implement with an LLM call (Claude, GPT-4o, …) or a deterministic * heuristic. Must always resolve — never reject. * * @param goal - The original user goal * @param blackboardSummary - A serialisable snapshot of the current blackboard */ export type CoverageEvaluatorFunction = (goal: string, blackboardSummary: Record) => Promise; /** Options for {@link CoverageGate}. */ export interface CoverageGateOptions { /** * Minimum score (0–100) needed to pass the gate. * Default: 90. */ threshold?: number; /** * Maximum number of refinement rounds before accepting the result even if * the threshold is not met. Prevents infinite loops. * Default: 3. */ maxRefinements?: number; } /** Outcome of a single {@link CoverageGate.evaluate} call. */ export interface CoverageGateResult { /** Whether the gate was passed (score ≥ threshold). */ passed: boolean; /** The evaluation result from the evaluator. */ evaluation: CoverageResult; /** The threshold that was applied. */ threshold: number; /** Number of refinement rounds that have been run so far. */ refinementsUsed: number; /** Whether the maximum refinements limit was reached. */ maxRefinementsReached: boolean; } /** Describes one pass through the coverage refinement loop. */ export interface RefinementRound { round: number; evaluation: CoverageResult; passed: boolean; gapsRequeued: string[]; } /** * A simple keyword-gap evaluator that checks whether each expected topic * keyword appears anywhere in the stringified blackboard values. * * Useful for deterministic tests and quick smoke-tests without an LLM. * * @param expectedTopics - List of keywords/phrases that must appear in the board */ export declare function createKeywordEvaluator(expectedTopics: string[]): CoverageEvaluatorFunction; /** * Build an evaluator backed by an LLM via the Network-AI executor API. * * @param executor - Network-AI executor function * @param evaluatorAgentId - Agent ID for the evaluator model */ export declare function createLLMEvaluator(executor: (agentId: string, payload: { action: string; params: Record; }, context: { agentId: string; taskId: string; metadata?: Record; }) => Promise<{ success: boolean; data?: unknown; error?: { message: string; }; }>, evaluatorAgentId: string): CoverageEvaluatorFunction; /** * CoverageGate is the final gatekeeper before `submit_final`. * * Call `evaluate()` after each execution round. If it returns `passed: false`, * use `result.evaluation.gaps` to generate additional sub-tasks via * GoalDecomposer, then re-run and evaluate again. * * @example * ```typescript * const gate = new CoverageGate(myLLMEvaluator, { threshold: 90, maxRefinements: 3 }); * * let boardSnapshot = blackboard.snapshot(); * let gateResult = await gate.evaluate(goal, boardSnapshot); * * while (!gateResult.passed && !gateResult.maxRefinementsReached) { * const gapGoal = `Fill these gaps: ${gateResult.evaluation.gaps.join(', ')}`; * const gapDag = await decomposer.decompose(gapGoal, agents); * await runner.run(gapDag, runOptions); * boardSnapshot = blackboard.snapshot(); * gateResult = await gate.evaluate(goal, boardSnapshot); * } * ``` */ export declare class CoverageGate { private evaluatorFn; private threshold; private maxRefinements; private _refinementsUsed; private _history; constructor(evaluatorFn: CoverageEvaluatorFunction, options?: CoverageGateOptions); /** * Evaluate the current blackboard state against the original goal. * * Each call increments the internal refinement counter. When * `maxRefinements` is reached the gate is treated as passed (fail-open) * to prevent infinite loops, and `maxRefinementsReached` is set to true. * * @param goal - Original user goal * @param blackboardSummary - Current blackboard snapshot (key → value) */ evaluate(goal: string, blackboardSummary: Record): Promise; /** Reset the refinement counter and history (allows reuse across separate goals). */ reset(): void; /** History of all refinement rounds evaluated so far. */ get history(): readonly RefinementRound[]; /** Current refinement count (before this becomes a pass-through). */ get refinementsUsed(): number; /** The configured threshold (0–100). */ get scoreThreshold(): number; } //# sourceMappingURL=coverage-gate.d.ts.map