export declare const BULK_CANDIDATE_REQUEST_LIMIT = 100; export interface CandidateRoundPreview { id: string; roundConfigId: string | null; name: string; roundType: string; emailLogs: ReadonlyArray<{ emailType: string; }>; } export interface BulkCandidateTarget { id: string; jobPostingId: string | null; interviewRounds: ReadonlyArray; } export interface CandidateTargetPage { items: ReadonlyArray; total: number; hasMore: boolean; } export type CandidateMaterializationErrorCode = 'STALE_SCOPE' | 'TOTAL_DRIFT' | 'EMPTY_PAGE_WITH_MORE' | 'INVALID_PAGE_LENGTH' | 'UNIQUE_COUNT_MISMATCH' | 'MEMBERSHIP_DRIFT'; export declare class CandidateMaterializationError extends Error { readonly code: CandidateMaterializationErrorCode; constructor(code: CandidateMaterializationErrorCode, message: string); } interface MaterializeCandidateTargetsOptions { scopeKey: string; expectedTotal: number; fetchPage: (limit: number, offset: number) => Promise>; getCurrentScopeKey: () => string; pageSize?: number; } /** * Materializes a frozen application-filter scope without trusting cached pages. * Two independent passes must return the same ordered target snapshots. This * catches offset-page membership shifts while preserving the 100-item page cap. */ export declare function materializeCandidateTargets({ scopeKey, expectedTotal, fetchPage, getCurrentScopeKey, pageSize, }: MaterializeCandidateTargetsOptions): Promise; interface MaterializeCandidateTargetsByIdsOptions { scopeKey: string; applicationIds: ReadonlyArray; fetchChunkPage: (applicationIds: ReadonlyArray, limit: number, offset: number) => Promise>; getCurrentScopeKey: () => string; } /** * Revalidates selected candidates in bounded ID chunks. Each chunk is filtered * by both its IDs and the frozen list filter, so earlier mutations cannot make * later validation rescan or reinterpret the full result set. */ export declare function materializeCandidateTargetsByIds({ scopeKey, applicationIds, fetchChunkPage, getCurrentScopeKey, }: MaterializeCandidateTargetsByIdsOptions): Promise; export interface CandidateSelectionState { mode: 'explicit' | 'all'; explicitIds: ReadonlySet; allTargetIds: ReadonlySet; excludedIds: ReadonlySet; } export declare function createEmptyCandidateSelection(): CandidateSelectionState; export declare function selectAllMaterializedCandidates(applicationIds: ReadonlyArray): CandidateSelectionState; export declare function getSelectedCandidateIds(selection: CandidateSelectionState): Set; export declare function getCandidateSelectionCount(selection: CandidateSelectionState): number; export declare function toggleCandidateSelection(selection: CandidateSelectionState, applicationId: string): CandidateSelectionState; export declare function setVisibleCandidateSelection(selection: CandidateSelectionState, visibleApplicationIds: ReadonlyArray, selected: boolean): CandidateSelectionState; export declare function getCandidateSelectionSummary(selection: CandidateSelectionState): string | null; export interface ExactRoundPair { applicationId: string; roundId: string; target: BulkCandidateTarget; round: CandidateRoundPreview; } export interface UnresolvedCandidateRound { target: BulkCandidateTarget; reason: 'MISSING' | 'AMBIGUOUS'; } export interface ExactRoundResolution { pairs: ExactRoundPair[]; unresolved: UnresolvedCandidateRound[]; } /** Resolve only concrete rounds with the requested config ID; never guess by name or type. */ export declare function resolveExactCandidateRounds(targets: ReadonlyArray, roundConfigId: string): ExactRoundResolution; export declare class CandidateChunkPreconditionError extends Error { constructor(message: string); } export declare function assertCandidateChunkMatchesCurrentScope(applicationIds: ReadonlyArray, currentTargets: ReadonlyArray, jobPostingId: string): void; export declare function assertCandidateEmailChunkMatchesCurrentScope(items: ReadonlyArray<{ applicationId: string; roundId: string; }>, currentTargets: ReadonlyArray, jobPostingId: string, roundConfigId: string): void; export declare function chunkCandidateRequests(items: ReadonlyArray, chunkSize?: number): T[][]; export interface SequentialExecutionProgress { processed: number; total: number; } export interface SequentialExecutionResult { aggregate: TAggregate; processedItems: TItem[]; ambiguousItems: TItem[]; notStartedItems: TItem[]; error: unknown | null; } interface ExecuteSequentialCandidateChunksOptions { items: ReadonlyArray; initialAggregate: TAggregate; executeChunk: (chunk: ReadonlyArray, chunkIndex: number) => Promise; mergeResult: (aggregate: TAggregate, result: TBatchResult) => TAggregate; onProgress?: (progress: SequentialExecutionProgress) => void; chunkSize?: number; } /** * Executes each request once and in order. A thrown transport/missing-data error * makes the current chunk ambiguous and prevents every later chunk from starting. */ export declare function executeSequentialCandidateChunks({ items, initialAggregate, executeChunk, mergeResult, onProgress, chunkSize, }: ExecuteSequentialCandidateChunksOptions): Promise>; export type BulkOperationNotificationSeverity = 'success' | 'warning' | 'error'; export declare function getBulkOperationNotificationSeverity({ succeeded, skipped, failed, ambiguous, }: { succeeded: number; skipped: number; failed: number; ambiguous?: boolean; }): BulkOperationNotificationSeverity; export interface CandidateEmailSuccess { applicationId: string; roundId: string; } export interface CandidateEmailSkip { applicationId: string; roundId: string; reason: string; message: string; } export interface CandidateEmailFailure { applicationId: string; roundId: string; message: string; } export interface CandidateEmailAggregate { succeeded: CandidateEmailSuccess[]; skipped: CandidateEmailSkip[]; failed: CandidateEmailFailure[]; } export declare function createEmptyCandidateEmailAggregate(): CandidateEmailAggregate; export declare function assertCompleteCandidateEmailChunkResult(requested: ReadonlyArray<{ applicationId: string; roundId: string; }>, result: CandidateEmailAggregate): void; export declare function aggregateCandidateEmailResult(aggregate: CandidateEmailAggregate, result: CandidateEmailAggregate): CandidateEmailAggregate; export interface EnsuredRoundSummary { id: string; applicationId: string; } export interface EnsureRoundFailure { applicationId: string; code: string; message: string; } export interface EnsureRoundAggregate { created: EnsuredRoundSummary[]; alreadyPresent: EnsuredRoundSummary[]; failed: EnsureRoundFailure[]; } export declare function createEmptyEnsureRoundAggregate(): EnsureRoundAggregate; export declare function assertCompleteEnsureRoundChunkResult(requestedApplicationIds: ReadonlyArray, result: EnsureRoundAggregate): void; export declare function aggregateEnsureRoundResult(aggregate: EnsureRoundAggregate, result: EnsureRoundAggregate): EnsureRoundAggregate; export interface BulkCustomEmailSuccess { applicationId: string; email: string; } export interface BulkCustomEmailFailureItem { applicationId: string; message: string; } export interface BulkCustomEmailAggregate { succeeded: BulkCustomEmailSuccess[]; failed: BulkCustomEmailFailureItem[]; } export declare function createEmptyBulkCustomEmailAggregate(): BulkCustomEmailAggregate; export declare function assertCompleteBulkCustomEmailChunkResult(requestedApplicationIds: ReadonlyArray, result: BulkCustomEmailAggregate): void; export declare function aggregateBulkCustomEmailResult(aggregate: BulkCustomEmailAggregate, result: BulkCustomEmailAggregate): BulkCustomEmailAggregate; export interface BulkStatusUpdateSuccess { applicationId: string; status: string; } export interface BulkStatusUpdateFailureItem { applicationId: string; message: string; } export interface BulkStatusUpdateAggregate { succeeded: BulkStatusUpdateSuccess[]; failed: BulkStatusUpdateFailureItem[]; } export declare function createEmptyBulkStatusUpdateAggregate(): BulkStatusUpdateAggregate; export declare function assertCompleteBulkStatusUpdateChunkResult(requestedApplicationIds: ReadonlyArray, result: BulkStatusUpdateAggregate): void; export declare function aggregateBulkStatusUpdateResult(aggregate: BulkStatusUpdateAggregate, result: BulkStatusUpdateAggregate): BulkStatusUpdateAggregate; export declare function hasCandidateEmailType(round: CandidateRoundPreview, emailType: string): boolean; export interface DuplicateNoticeSuccess { email: string; } export interface DuplicateNoticeSkip { email: string; reason: string; message: string; } export interface DuplicateNoticeFailure { email: string; message: string; } export interface DuplicateNoticeAggregate { succeeded: DuplicateNoticeSuccess[]; skipped: DuplicateNoticeSkip[]; failed: DuplicateNoticeFailure[]; } export declare function createEmptyDuplicateNoticeAggregate(): DuplicateNoticeAggregate; export declare function aggregateDuplicateNoticeResult(aggregate: DuplicateNoticeAggregate, result: DuplicateNoticeAggregate): DuplicateNoticeAggregate; export {};