/**
 * Hook dispatcher: turns a runtime `Event` + loaded packs into a Claude Code
 * hook decision (`exit code 0 = allow | 2 = block` + optional stderr message).
 *
 * Sits between the per-host hook binaries (`pre-tool-use.ts`, `stop.ts`,
 * `user-prompt-submit.ts`, `session-end.ts`) and the rule evaluator. Each hook
 * binary is a thin shell that:
 *   1. Reads stdin → parses into an Event of the right `kind`.
 *   2. Loads active packs + builds the function registry (bootstrap.ts).
 *   3. Calls `dispatchEvent` to produce `{ exitCode, stderr }`.
 *   4. Writes stderr, exits with the code.
 *
 * The dispatcher walks `packs × skills × rules`, runs each rule's process via
 * `evaluateProcess`, and short-circuits on the FIRST verdict. The first-match
 * semantics matter: a high-priority pack's block decision must not be
 * overridden by a later pack's warn. Pack ordering is the loader's
 * responsibility (Task 1.19); the dispatcher trusts the order it's given.
 *
 * AUTO.1 event-kind filter: before walking a skill's rules, the dispatcher
 * checks `event.kind ∈ skill.triggers.map(t => t.kind)`. Skills that don't
 * subscribe to the incoming event kind are skipped entirely. This keeps
 * tool-call hooks from re-running schedule/webhook/file-changed skills and
 * vice versa. A skill that wants to fire on multiple kinds lists them all
 * (e.g. `triggers: [{kind: tool_call}, {kind: schedule, cron: ...}]`). The
 * default trigger list (when the YAML block is omitted) is a single
 * `tool_call` entry — preserves Phase 1–7 dispatcher behavior verbatim.
 *
 * Drift-response policy resolution:
 *   1. Pack-shipped `drift_response.yaml` → `Pack.driftResponse` (loaded by
 *      `loadPack`). For each fired rule, the dispatcher consults
 *      `pack.driftResponse?.per_rule[rule.id] ?? pack.driftResponse?.default`.
 *   2. Pack without `drift_response.yaml` → falls back to `defaultPolicyForLevel`,
 *      which DERIVES the policy from the fired verdict's `level` (block →
 *      block_tool; warn/surface/pass/directive → warn). This honors the
 *      author's `level:` by default — a `level: warn` rule warns instead of
 *      hard-blocking — so a policy file is an OVERRIDE, not a prerequisite for
 *      level-correct behavior. (Replaces the old blanket `block_tool` default,
 *      which discarded the level.)
 *   3. `corrective_skills` map (`auto_correct` policy support) is threaded
 *      into `applyDriftResponse` via the `DriftDispatchCtx` argument so
 *      `auto_correct` policies can look up their corrective skill name.
 *
 * Pack-agnostic discipline: the dispatcher does NOT special-case
 * sangmin-personal-rules or any other named pack. It reads whatever each
 * pack's `driftResponse` field contains; missing/empty/absent all flow
 * through the same `??` chain.
 *
 * Exit-code mapping (Claude Code hook protocol):
 *   block_tool   → { exitCode: 2, stderr: message }
 *   warn         → { exitCode: 0, stderr: message }   (allow, but surface)
 *   halt         → { exitCode: 0, stderr: '' }        (Task 1.14 wires real halt)
 *   notify_pause → { exitCode: 0, stderr: '' }        (Task 1.18 wires channels)
 *
 * Halt and notify_pause exit 0 deliberately for Phase 1: the runtime can't
 * actually halt the parent agent's task loop from a hook, and channel
 * notifications need infrastructure that doesn't ship until later phases.
 * Mapping them to exit 0 means a misconfigured pack-declared policy won't
 * silently block tools during Phase 1; the real behavior lands when its
 * machinery does.
 *
 * Imports from: runtime/types.js, runtime/evaluator.js, runtime/drift_response.js,
 * functions/registry.js.
 * Imported by: runtime/hooks/*.ts (per-hook binaries).
 */
import type { FunctionRegistry } from '../../functions/registry.js';
import { type TickState } from '../unload_conditions.js';
import type { ActivationScope } from '../../packs/schemas/manifest.js';
import type { Directive, Event, Pack, Skill } from '../types.js';
export interface DispatchResult {
    exitCode: 0 | 2;
    stderr: string;
    /**
     * G.4 — aggregated `inject_context` payloads from every skill that fired
     * during this dispatch. Empty array on the common (no-injection) path.
     *
     * Only the `UserPromptSubmit` hook bin actually emits these as host
     * context (Claude Code's `hookSpecificOutput.additionalContext` JSON
     * envelope). Other hook bins ignore the array (the dispatcher writes a
     * stderr warning when an `inject_context` fires on a non-`prompt_submit`
     * event so misconfiguration is visible).
     *
     * Block-verdict + inject_context COEXIST: the block wins on `exitCode`,
     * but the injections are still aggregated and returned so the user sees
     * the recall context alongside the block message. Per Phase-2 lock #7.
     */
    contextInjections: string[];
    /**
     * T-ASC ASC.3 — aggregated `directive`-level verdicts from every rule
     * that fired. Peer to `contextInjections`; same dispatcher-side flow
     * (aggregate-everywhere, surface-via-prompt_submit). The UserPromptSubmit
     * hook bin serializes the array as a fenced JSON block under a
     * `⛔ DIRECTIVE` marker inside the same `additionalContext` envelope key
     * (no new envelope keys — Claude Code 2.x doesn't reliably honor unknown
     * ones).
     *
     * Block-verdict + directive COEXIST identically to inject_context: a
     * block emitted by a LATER rule still raises exitCode 2, but directives
     * emitted by EARLIER rules still surface on stdout so the agent sees
     * both the next-action handoff and the block message.
     */
    directives: Directive[];
}
/**
 * The per-skill unload gate decision (pure, testable). A DYNAMIC skill is
 * skipped this event ⟺ it has a tick AND `shouldUnload(unloads_when, tick)`
 * fires. FAIL-SAFE = default-LOADED: a missing tick (`undefined`) NEVER
 * skips — silently skipping a gate skill because its tick read failed would
 * be a drift hole. Pinned skills never reach this function.
 */
/**
 * IDF.4 — activation_scope dispatch routing.
 *
 * Per-pack `activation_scope:` (v0.6 §4.5 restored by IDF.1 schema) gates
 * whether the dispatcher should walk a pack's skills at all in the current
 * context. Distinct axis from existing `scope:` (which is layering
 * precedence — universal→domain→specialty→workflow→project).
 *
 * 5-case semantics (per T-IDENTITY-FOUNDATION L7):
 *   - 'project'  → applies when current cwd matches project context
 *   - 'user'     → always applies (per-user globally)
 *   - 'hybrid'   → both project AND user signals must apply
 *   - 'team'     → ships INERT — never fires until team-mode lands.
 *                  Packs declaring this scope are silently dormant; users
 *                  shipping team packs today should know this.
 *   - 'global'   → effectively == 'user' today; distinguishing requires
 *                  multi-user infrastructure (post-v1).
 */
export interface DispatchScopeCtx {
    /** True when current cwd matches the pack's project context (today: always true when discovery loaded the pack at all). */
    inProject: boolean;
    /** Always true today; placeholder for future team/multi-user infrastructure. */
    isUserSession: boolean;
}
/**
 * LL.3 — inbound_channel trigger filter. Honors optional `channel:` literal
 * (matched against the scheme prefix of `event.channelUri`) and optional
 * `sender_pattern` regex (matched against `event.sender`). Empty/absent
 * fields are accept-all per back-compat. Malformed regex → no match.
 */
interface InboundChannelTrigger {
    kind: 'inbound_channel';
    channel?: string;
    sender_pattern?: string;
}
export declare function inboundChannelTriggerMatches(trigger: InboundChannelTrigger, event: Extract<Event, {
    kind: 'inbound_channel';
}>): boolean;
export declare function activationScopeApplies(scope: ActivationScope, ctx: DispatchScopeCtx): boolean;
export declare function shouldSkillUnload(skill: Skill, tick: TickState | undefined): boolean;
export declare function dispatchEvent(event: Event, packs: Pack[], registry: FunctionRegistry, sessionId: string, scopeCtx?: DispatchScopeCtx): Promise<DispatchResult>;
export {};
//# sourceMappingURL=dispatch.d.ts.map