/**
 * Pack discovery substrate (ADR-097 § 5 Q5 + § 10, mmnto-ai/totem#1768).
 *
 * Reads `.totem/installed-packs.json` synchronously at engine boot,
 * resolves each registered pack's registration callback module, and
 * invokes the callback with a `PackRegistrationAPI` so the pack can
 * register its ChunkStrategy + ast-grep Lang + WASM grammar entries
 * before the engine seals.
 *
 * Sealing happens at the end of `loadInstalledPacks()` after every pack
 * callback has returned. Once sealed, subsequent `register()` calls on
 * either registry throw — see `chunker-registry.ts:seal()` and
 * `ast-classifier.ts:sealLangRegistry()`.
 *
 * The seal is the only synchronization boundary between the registration
 * phase and the runtime phase. CLI commands invoke `loadInstalledPacks()`
 * immediately after config load and before any other engine surface, so
 * pack registration is always complete before any chunker / language
 * lookup happens.
 *
 * Failure-mode discipline (Tenet 4):
 * - Missing manifest: silent (treated as no packs); user runs `totem sync`
 *   to generate.
 * - Malformed manifest: hard error.
 * - Pack require throws: hard error.
 * - engines['@mmnto/totem'] version mismatch: structured error per ADR-097
 *   Q6 (amended 2026-05-03 — moved from peerDependencies to engines field
 *   per mmnto-ai/totem#1803 to avoid changesets `fixed` group sibling
 *   peer-dep collision; see #1776 / #1777).
 * - Pack callback throws: hard error.
 */
import { z } from 'zod';
import { type SupportedLanguage } from './ast-classifier.js';
import type { Chunker } from './chunkers/chunker.js';
/**
 * `.totem/installed-packs.json` substrate. Written by `totem sync`,
 * consumed by `loadInstalledPacks()` at boot.
 *
 * `version: 1` is the load-bearing sentinel for forward compatibility:
 * future schema changes bump the version, callers fail loud on unknown
 * versions rather than silently mis-parsing.
 */
export declare const InstalledPacksManifestSchema: z.ZodEffects<z.ZodObject<{
    version: z.ZodLiteral<1>;
    /**
     * `@mmnto/totem` package version that wrote the manifest. Optional
     * for forward-compat with pre-1.27.0 manifests. Stamped at write
     * time by `writeInstalledPacksManifest()` from `resolveEngineVersion()`.
     *
     * Read on the lint-time stale-manifest UX-nudge fast-path
     * (`rule-engine.ts` parser-error intercept). Schema does not
     * enforce semver-validity here so a malformed cohort doesn't make
     * the entire manifest unreadable; the consumer treats malformed
     * or missing values as "stale" and surfaces the same nudge
     * (mmnto-ai/totem#1811, ADR-101).
     */
    cohort: z.ZodOptional<z.ZodString>;
    packs: z.ZodArray<z.ZodObject<{
        /** Pack package name as it appears in npm (e.g., `@mmnto/pack-rust-architecture`). */
        name: z.ZodString;
        /**
         * Absolute filesystem path to the pack's package root. Refined to
         * `path.isAbsolute()` so a relative entry can't pass schema
         * validation and then probe two different locations downstream
         * (`existsSync` resolves from cwd, `require.resolve` from this
         * module).
         */
        resolvedPath: z.ZodEffects<z.ZodString, string, string>;
        /**
         * The pack's `engines['@mmnto/totem']` semver range, verbatim.
         * (Pre-1.26.0 packs used `peerDependencies['@mmnto/totem']`;
         * mmnto-ai/totem#1803 moved the constraint to the `engines`
         * field to free `peerDependencies` for actual peer packages
         * and avoid changesets fixed-group sibling collisions.)
         */
        declaredEngineRange: z.ZodString;
    }, "strict", z.ZodTypeAny, {
        name: string;
        resolvedPath: string;
        declaredEngineRange: string;
    }, {
        name: string;
        resolvedPath: string;
        declaredEngineRange: string;
    }>, "many">;
}, "strict", z.ZodTypeAny, {
    version: 1;
    packs: {
        name: string;
        resolvedPath: string;
        declaredEngineRange: string;
    }[];
    cohort?: string | undefined;
}, {
    version: 1;
    packs: {
        name: string;
        resolvedPath: string;
        declaredEngineRange: string;
    }[];
    cohort?: string | undefined;
}>, {
    version: 1;
    packs: {
        name: string;
        resolvedPath: string;
        declaredEngineRange: string;
    }[];
    cohort?: string | undefined;
}, {
    version: 1;
    packs: {
        name: string;
        resolvedPath: string;
        declaredEngineRange: string;
    }[];
    cohort?: string | undefined;
}>;
export type InstalledPacksManifest = z.infer<typeof InstalledPacksManifestSchema>;
/**
 * Surface a pack's registration callback uses to extend the engine's
 * built-in chunker + language tables. Callbacks are synchronous (per
 * ADR-097 § 5 Q5 — boot must remain synchronous); WASM grammar bytes
 * load lazily on first ast-grep dispatch via the `wasmLoader` thunk.
 */
export interface PackRegistrationAPI {
    /**
     * Register a pack-contributed `ChunkStrategy` name + chunker class.
     * The strategy name appears in `targets[].strategy` validation and
     * `totem describe` output. Built-in names are immutable; pack-vs-pack
     * collisions on the same name throw.
     */
    registerChunkStrategy(name: string, chunkerCtor: new () => Chunker): void;
    /**
     * Register a pack-contributed (extension, language, wasmLoader) triple.
     * The extension flows through `extensionToLanguage()` for ast-grep
     * dispatch; the language drives `loadGrammar()`; the wasmLoader thunk
     * resolves the grammar bytes lazily on first use.
     *
     * Built-in extensions/languages are immutable; pack-vs-pack collisions
     * on the same extension throw.
     */
    registerLanguage(extension: string, lang: SupportedLanguage, wasmLoader: () => string | Uint8Array | Promise<string | Uint8Array>): void;
}
/**
 * The shape a pack's registration callback module must export. Packs
 * default-export a function matching this signature; `loadInstalledPacks`
 * requires the module and invokes the function once with the API surface.
 */
export type PackRegisterCallback = (api: PackRegistrationAPI) => void;
/**
 * Runtime descriptor for a discovered + loaded pack. Returned from
 * `loadInstalledPacks` for diagnostics + `totem doctor` consumption.
 */
export interface LoadedPack {
    readonly name: string;
    readonly resolvedPath: string;
    readonly declaredEngineRange: string;
}
/** Options for `loadInstalledPacks` — primarily test-driven overrides. */
export interface LoadInstalledPacksOptions {
    /**
     * Project root for manifest resolution. The manifest is expected at
     * `<projectRoot>/<totemDir>/installed-packs.json`. Defaults to
     * `process.cwd()` when omitted.
     */
    projectRoot?: string;
    /**
     * `config.totemDir` from the resolved totem config. Defaults to
     * `'.totem'` so callers without a loaded config (e.g., simple CLIs,
     * tests) work out of the box.
     */
    totemDir?: string;
    /**
     * Engine semver to compare against each pack's declared
     * `engines['@mmnto/totem']` range. Defaults to the engine's
     * own `package.json#version`.
     */
    engineVersion?: string;
    /**
     * Test-only escape hatch: list of `{ pack, callback }` tuples that
     * bypass the manifest read + `require()` resolution and feed callbacks
     * directly into the registration phase. Useful for unit tests that
     * register fixture chunkers/languages without writing fixture packages
     * to disk.
     *
     * When provided, the manifest read is skipped entirely; only these
     * inMemoryPacks run.
     */
    inMemoryPacks?: ReadonlyArray<{
        pack: LoadedPack;
        callback: PackRegisterCallback;
    }>;
}
/**
 * Read `.totem/installed-packs.json` and run every registered pack's
 * registration callback synchronously. After all callbacks return, seal
 * both the chunker registry and the language registry.
 *
 * Idempotent: a second call after the first throws because the engine is
 * already sealed (callers must not "re-load" packs at runtime). For
 * tests, see `__resetForTests()`.
 */
export declare function loadInstalledPacks(options?: LoadInstalledPacksOptions): readonly LoadedPack[];
/**
 * Snapshot of currently-loaded packs. Empty until `loadInstalledPacks()`
 * runs; populated thereafter and stable for the engine lifetime.
 */
export declare function loadedPacks(): readonly LoadedPack[];
/** True iff the engine has sealed (registration phase complete). */
export declare function isEngineSealed(): boolean;
/**
 * Resolve the running `@mmnto/totem` package version from disk.
 *
 * Exported (mmnto-ai/totem#1811) so `pack-manifest-writer.ts` can
 * stamp the manifest's `cohort` field at write time and the
 * `rule-engine.ts` parser-error intercept can compare the running
 * engine against the manifest's recorded cohort.
 */
export declare function resolveEngineVersion(): string;
/**
 * Test-only: reset pack-discovery local state (`PACK_REGISTRY` map and
 * `engineSealed` flag). NEVER call from production.
 *
 * **This does NOT reset downstream registries.** Tests that need a
 * fresh chunker or language registry must additionally invoke
 * `__resetForTests` from `chunker-registry.js` and `ast-classifier.js`
 * — those modules own their own lifecycle. Forgetting either reset
 * leaks built-in registrations across cases. The standard `afterEach`
 * pattern in `pack-discovery.test.ts` calls all three.
 */
export declare function __resetForTests(): void;
/** Test-only: inspect chunker registry seal state. */
export declare function __isChunkerRegistrySealedForTests(): boolean;
//# sourceMappingURL=pack-discovery.d.ts.map