/**
 * FeedbackProcessingService.ts — the production trigger that turns the already-
 * parity'd `processUnprocessed` clustering pass into a real, triggerable
 * capability (feedback-factory-migration spec §191: "the processor job is
 * actually constructed and scheduled, not dead code").
 *
 * It owns a single `JsonlFeedbackStore` rooted at the CANONICAL store directory —
 * the SAME directory the InboxDrainer fills (so the processor clusters the exact
 * reports the receiving end ingested). Two surfaces ride this service:
 *
 *   - `GET  /feedback-factory/stats`   → stats() (pure read; never mutates)
 *   - `POST /feedback-factory/process` → processNow() (one clustering pass)
 *
 * Both are dev-gated at the construction boundary (resolveDevAgentGate over
 * feedbackFactory.processing.enabled): the service is constructed only when the
 * gate is live; otherwise the route context holds null and both routes 503.
 *
 * Signal-vs-authority: processNow only appends local JSONL — it creates/merges
 * dedup clusters and flips items unprocessed→processing. It takes NO external
 * action (dispatch is not invoked here) and never force-closes a curated
 * cluster (terminal transitions stay evidence-gated in the processor itself).
 * Re-running is idempotent and forward-only: once an item is 'processing' it is
 * no longer 'unprocessed', so a second pass is a no-op over it.
 */
import type { ProcessResult } from '../processor/process.js';
export interface FeedbackProcessingStats {
    total: number;
    byStatus: Record<string, number>;
    clusterCount: number;
    dispatchCount: number;
    lastWriteAt: string | null;
}
export interface FeedbackProcessingServiceOptions {
    /** Canonical store directory. Resolve via resolveCanonicalStoreDir() so it
     *  matches the InboxDrainer's store exactly. */
    dataDir: string;
}
export declare class FeedbackProcessingService {
    private readonly store;
    constructor(opts: FeedbackProcessingServiceOptions);
    /** Pure read — the GET /feedback-factory/stats surface. */
    stats(): FeedbackProcessingStats;
    /**
     * Run one clustering+apply pass over the canonical store and return the
     * processor result plus the post-pass stats. `now` is injected for the reopen
     * audit note (defaults to wall-clock ISO). Appends local JSONL only.
     */
    processNow(now?: string): {
        result: ProcessResult;
        stats: FeedbackProcessingStats;
    };
}
/**
 * The canonical feedback-factory store directory. Mirrors the InboxDrainer
 * resolution exactly: an explicit `processing.dataDir` wins, else the
 * receiverPersistence `dataDir` (so the two ends share one store), else the
 * shipped default `<stateDir>/state/feedback-factory/store`.
 */
export declare function resolveCanonicalStoreDir(config: {
    stateDir?: string;
    feedbackFactory?: {
        processing?: {
            dataDir?: string;
        };
        receiverPersistence?: {
            dataDir?: string;
        };
    };
}): string | null;
//# sourceMappingURL=FeedbackProcessingService.d.ts.map