/**
 * Tool Policy Engine — facade class (M8 — see
 * `.cursor/plans/m8-design.md` § 2).
 *
 * Wraps `composeDecision(...)` with engine-instance state:
 *   - bound inputs (`tools`, `assessment`, `currentItemRef`, ...)
 *   - registered custom `PolicySource`s
 *   - `onPolicyChange` subscriber bus
 *   - `dispose()` clean-up
 *
 * The class has no DOM dependency and no Svelte runes. It is safe to
 * instantiate inside a worker, in a Node test, or inside a CE
 * connectedCallback. The Svelte context glue (`TOOL_POLICY_ENGINE_KEY`)
 * lives in `engine-context.ts`.
 *
 * PR 1 ships the engine *without callers*. PR 2 wires it into
 * `ToolkitCoordinator`. PR 3 switches `<pie-item-toolbar>` over.
 */
import type { AssessmentEntity, AssessmentItemRef } from "@pie-players/pie-players-shared/types";
import type { CanonicalToolsConfig, ToolPlacementLevel } from "../../services/tools-config-normalizer.js";
import type { ToolRegistry } from "../../services/ToolRegistry.js";
import type { ToolPolicyDecision, ToolPolicyDecisionRequest } from "./decision-types.js";
import type { PolicySource } from "./PolicySource.js";
export type PnpEnforcementMode = "on" | "off";
export interface ToolPolicyEngineInputs {
    tools?: CanonicalToolsConfig | null;
    assessment?: AssessmentEntity | null;
    currentItemRef?: AssessmentItemRef | null;
    /**
     * Explicit PNP/profile override. When omitted (or `undefined`), the engine
     * defaults to {@link resolveDefaultPnpEnforcement} over the bound
     * `assessment` and `currentItemRef`: `"on"` if they carry any
     * PNP/profile policy material (PNP, district policy, test
     * administration, item-level required/restricted/parameters),
     * `"off"` otherwise. See `.cursor/plans/m8-design.md` F2.
     *
     * Hosts that want to force a mode pass `"on"` or `"off"`
     * explicitly. Embedded under `<pie-section-player-*>` the preferred
     * override flows through `runtime.tools.pnpEnforcement`.
     */
    pnpEnforcement?: PnpEnforcementMode;
}
export interface ToolPolicyEngineArgs {
    toolRegistry: ToolRegistry;
    inputs?: ToolPolicyEngineInputs;
    customSources?: readonly PolicySource[];
    /** Stable context label used in provenance trails. Defaults to "tool-policy". */
    contextId?: string;
}
export interface ToolPolicyChangeEvent {
    /** What changed in this update. */
    reason: "inputs" | "policy-source-added" | "policy-source-removed" | "pnp-enforcement" | "disposed";
    /** Snapshot of the engine's inputs after the change. */
    inputs: Readonly<ResolvedEngineInputs>;
}
export interface ResolvedEngineInputs {
    tools: CanonicalToolsConfig;
    assessment: AssessmentEntity | null;
    currentItemRef: AssessmentItemRef | null;
    pnpEnforcement: PnpEnforcementMode;
}
export type ToolPolicyChangeListener = (event: ToolPolicyChangeEvent) => void;
export declare class ToolPolicyEngine {
    private readonly toolRegistry;
    private readonly contextId;
    private readonly pnpPolicySource;
    private readonly customSources;
    private readonly listeners;
    private tools;
    private assessment;
    private currentItemRef;
    private pnpEnforcement;
    private disposed;
    constructor(args: ToolPolicyEngineArgs);
    /**
     * Resolve the visible tool set for a given placement level and
     * scope.
     *
     * `visibleTools` and `diagnostics` are deterministic with respect
     * to the engine's currently-bound inputs — calling `decide(...)`
     * twice with identical inputs returns structurally equal
     * `visibleTools` and `diagnostics`. The returned `provenance`
     * carries call-time `evaluatedAt` timestamps generated by
     * `ToolPolicyProvenanceBuilder` (one per `decide(...)`); two
     * back-to-back calls therefore produce different `evaluatedAt`
     * values even though the policy decision itself is identical.
     * Hosts that want timestamp-stable provenance should reuse a
     * cached `ToolPolicyDecision` rather than re-call `decide(...)`.
     */
    decide(request: ToolPolicyDecisionRequest): ToolPolicyDecision;
    /**
     * Convenience wrapper for hosts that just want the visible tool
     * IDs. Equivalent to `decide(...).visibleTools.map(e => e.toolId)`.
     */
    getVisibleToolIds(level: ToolPlacementLevel, scopeId: string): string[];
    /**
     * Apply a partial input update.
     *
     * Each key is value-diffed via `Object.is` before storing, so callers
     * may safely re-push the same reference (e.g. on Svelte effect
     * re-runs caused by unrelated tracked reads): no-op patches do not
     * fire `onPolicyChange` listeners. This contract is relied on by
     * `PieAssessmentToolkit.svelte`'s prop-forwarding effect and by the
     * coordinator's `decideToolPolicy()` tests.
     *
     * `pnpEnforcement` is stored on its own field and always emits with
     * a distinct `"pnp-enforcement"` reason when no other key changed,
     * so PR 4's auto-on flip can target that reason without a separate
     * event channel.
     */
    updateInputs(patch: Partial<ToolPolicyEngineInputs>): void;
    registerPolicySource(source: PolicySource): () => void;
    onPolicyChange(listener: ToolPolicyChangeListener): () => void;
    getInputs(): Readonly<ResolvedEngineInputs>;
    dispose(): void;
    private snapshotInputs;
    private emit;
    private assertNotDisposed;
}
