import { DrizzleClient } from '../../types/drizzle.js';
import { DrizzleTransaction } from '../events/event-bus.protocol.js';
import { I as IJobOrchestrator, l as StartOptions, i as JobRun, C as CancelOptions, j as JobUpsertEntry, h as JobPoolDef } from '../../../job-orchestrator.protocol-DubMVbm9.js';
import 'drizzle-orm/node-postgres';
import './job-orchestration.schema.js';
import 'drizzle-orm/pg-core';
import 'drizzle-orm';
import '@nestjs/common';
import '../events/event-registry.js';

/**
 * Terminal statuses — transitions into these are final. Used by `cancel`
 * (to short-circuit idempotently) and by `replay` (as the guard gate).
 */
declare const TERMINAL_STATUSES: readonly ["completed", "failed", "timed_out", "canceled"];
/**
 * Substitute `{{field}}` placeholders against the input payload.
 *
 * Implementation decision (JOB-3, 2026-04-19): simple `{{field}}` single-key
 * substitution, no dotted paths, no Mustache/Handlebars dependency. A missing
 * field throws `JobTemplateFieldMissingError` synchronously — cheaper than
 * discovering the misconfiguration at claim time.
 */
declare function evaluateKeyTemplate(template: string, input: Record<string, unknown>): string;
declare class DrizzleJobOrchestrator implements IJobOrchestrator {
    private readonly db;
    private readonly multiTenant;
    private readonly listenNotify;
    private readonly logger;
    constructor(db: DrizzleClient, multiTenant: boolean, listenNotify?: boolean);
    /**
     * JOB-8 — resolve `tenantId` for a mutating / targeted-read call.
     * Returns the tenant value that should be written to the row (or compared
     * against in a WHERE clause). When `multiTenant` is off, the column is
     * forced to `null` regardless of what callers pass. When on, `undefined`
     * throws; `null` and strings pass through untouched.
     */
    private resolveTenantId;
    start(type: string, input: unknown, opts?: StartOptions, tx?: DrizzleTransaction): Promise<JobRun>;
    cancel(runId: string, opts?: CancelOptions): Promise<void>;
    replay(runId: string): Promise<JobRun>;
    /**
     * Hash-gated `INSERT … ON CONFLICT (type) DO UPDATE … WHERE` per Q3
     * resolution (2026-04-19): the `UPDATE` branch executes only when one
     * of the persisted metadata fields differs from the incoming payload;
     * `version` bumps only on real change; concurrent boots with identical
     * content are idempotent no-ops.
     *
     * Why this shape (not `DO NOTHING`, not advisory locks):
     *   - `DO NOTHING` would let an old-version instance leave a stale row
     *     that a new-version instance can't overwrite during a rolling deploy.
     *   - Advisory locks add latency and leak risk under crashes.
     *   - The `WHERE … IS DISTINCT FROM …` clause makes the conditional
     *     atomic — no read-modify-write race on `version` between concurrent
     *     boots.
     *
     * Orphan detection: a single `SELECT type FROM job WHERE type NOT IN (...)`
     * returns the types present in DB but absent from `entries`. Caller (boot
     * validator) decides whether to throw `BootValidationError`.
     */
    upsertJobRows(entries: JobUpsertEntry[], poolConfig: ReadonlyMap<string, JobPoolDef>): Promise<{
        orphaned: string[];
    }>;
}

export { DrizzleJobOrchestrator, TERMINAL_STATUSES, evaluateKeyTemplate };
