/**
 * Normalise rule manifest.
 *
 * Single source of truth for every deterministic spec-reshape rule
 * applied between analyse (faithful extraction) and inference. Mirrors
 * the realize-rules manifest pattern (see `engines/src/realize/realize-rules.ts`):
 * one declaration per rule, three consumers (runner, per-rule corpus,
 * project-override loader).
 *
 * Phase 1a (engines 6.49.x) of the 2026-05-13-NORMALISE-PHASE proposal —
 * INFRASTRUCTURE only. The RULES array is empty in this phase; the
 * runner, manifest interface, and tests land first. Real rules
 * (`cluster-module-functions`, `crud-into-curved`,
 * `drop-trivial-passthrough`) land in Phase 2+.
 *
 * Why in engines/src/normalise/ (a new subsystem):
 *   Normalise is its own phase between analyse and inference, with its
 *   own pluggable rule set. Putting it under realize/ would conflate
 *   two different rule-classes (one for post-LLM-emit validation, one
 *   for pre-realize spec reshape). Following the entity-module
 *   colocation principle (R12), normalise gets its own home.
 */
import { CLUSTER_MODULE_FUNCTIONS_RULE } from './rules/cluster-module-functions.js';
import { CRUD_INTO_CURVED_RULE } from './rules/crud-into-curved.js';
import { DROP_TRIVIAL_PASSTHROUGH_RULE } from './rules/drop-trivial-passthrough.js';
/**
 * The canonical rule manifest. Append rules as they land. Order in
 * the array is informational only — the runner sorts by `ordering`.
 *
 * Phase 2 of `2026-05-13-NORMALISE-PHASE.md` §5:
 *   - `cluster-module-functions` (ordering 0): strip project-prefix
 *     from services synthesised by the module-functions adapter.
 *
 * Remaining rules (Phase 3-4 in §5):
 *   - `crud-into-curved`: collapse Service ops 1:1 with CURVED to entity
 *   - `drop-trivial-passthrough`: drop single-delegate-call ops
 */
export const RULES = [
    CLUSTER_MODULE_FUNCTIONS_RULE,
    CRUD_INTO_CURVED_RULE,
    DROP_TRIVIAL_PASSTHROUGH_RULE,
];
/**
 * Filter the manifest to rules applicable in `ctx`. Applies the
 * standard inclusion logic in one place:
 *
 *   1. `disabledRules` in ctx wins — always skip.
 *   2. `enabledByDefault: true` AND not in disabledRules → include.
 *   3. `enabledByDefault: false` AND id is in enabledRules → include.
 *   4. `appliesWhen` (when present) must return true.
 *
 * Returned rules are sorted by `ordering` ascending.
 */
export function rulesApplicableTo(ctx) {
    const disabled = ctx.disabledRules ?? new Set();
    const enabled = ctx.enabledRules ?? new Set();
    return RULES
        .filter((r) => {
        if (disabled.has(r.id))
            return false;
        const enabledByConfig = r.enabledByDefault || enabled.has(r.id);
        if (!enabledByConfig)
            return false;
        if (r.appliesWhen && !r.appliesWhen(ctx))
            return false;
        return true;
    })
        .slice()
        .sort((a, b) => a.ordering - b.ordering);
}
/**
 * Find a rule by id. Returns undefined when no rule with that id is
 * registered. Used by tests, project-override loaders, audit-trail
 * emission.
 */
export function getRule(id) {
    return RULES.find((r) => r.id === id);
}
//# sourceMappingURL=normalise-rules.js.map