/**
 * cluster.ts — TS port of the feedback-factory clustering driver.
 *
 * Byte-exact port of the decision loop in `cmd_cluster` (:1405) of the reference
 * `the-portal/.claude/scripts/feedback-processor.py`. Given the unprocessed items
 * and the active (status != 'resolved') clusters, decide for each item whether it
 * MERGES into an existing cluster or CREATES a new one, using Jaccard similarity
 * (similarity.ts, already parity-verified) over `"{title} {description}"`.
 *
 * This is the orchestration on top of the parity'd primitives. It is PURE: the
 * reference reads items+clusters from the DB, then runs this loop with no further
 * I/O (the DB writes happen separately in cmd_apply_clusters). So this ports as a
 * pure function and is parity-tested by monkeypatching the reference's DB query to
 * feed fixtures and running the REAL cmd_cluster loop.
 *
 * ORDER-DEPENDENT within a batch (by design, matching the reference + the spec):
 * a cluster created for an earlier item becomes a match candidate for later items.
 */
import type { FeedbackItem, Cluster, ClusterResult } from './types.js';
/**
 * Reproduce Python's `round(x, 3)` — round-half-to-even (banker's rounding) on the
 * float, to 3 decimals. JS `Math.round` is round-half-up, so a naive port diverges
 * on exact-half 4th decimals; this matches the reference. Verified by the parity
 * harness (which seeds an exact-half case).
 */
export declare function pyRound3(x: number): number;
/**
 * Port of cmd_cluster's decision loop. Mutates a working copy of `clusters` by
 * appending newly-created clusters (so later items can match them), exactly as the
 * reference does. Returns one ClusterResult per item.
 */
export declare function clusterItems(items: FeedbackItem[], clusters: Cluster[]): ClusterResult[];
//# sourceMappingURL=cluster.d.ts.map