/**
 * `installed-packs.json` writer (mmnto-ai/totem#1768, Step 4).
 *
 * Walks two source surfaces — the consumer's `package.json` dependencies
 * for `@mmnto/pack-*` entries, and the consumer's `totem.config.ts`
 * `extends` array — deduplicates, resolves each pack's installed path
 * via npm/pnpm semantics, and writes `.totem/installed-packs.json` for
 * `pack-discovery.ts:loadInstalledPacks()` to consume at boot.
 *
 * Mismatch handling (ADR-097 § 5 Q4 + Open Question 4 disposition):
 * - In both surfaces: union, no warning.
 * - In `extends` only (declared but not resolvable via npm): emit a
 *   warning naming the pack; skip from the manifest. Consumer must
 *   `pnpm add` the pack to make it work.
 * - In `package.json` only (resolvable but not declared in extends):
 *   emit a warning; skip from the manifest. Pack-merge only consumes
 *   `extends`-declared packs; including the dep-only entry would be
 *   misleading.
 *
 * Atomic write semantics: the writer goes through a temp file +
 * rename, mirroring `writeReviewExtensionsFile` (mmnto-ai/totem#1527).
 *
 * Filesystem access happens at the CLI boundary (this module is invoked
 * by `syncCommand`); the resolver itself takes paths + content as
 * inputs so tests can drive it without disk I/O.
 */
import type { TotemConfig } from './config-schema.js';
import type { InstalledPacksManifest } from './pack-discovery.js';
export interface PackResolutionWarning {
    /** Pack name surfaced in the warning. */
    readonly name: string;
    /**
     * Why the pack didn't make it to the manifest. Two shapes:
     *
     * - `dep-only`: present in package.json but not declared in
     *   `totem.config.ts` `extends`. Skipped because pack-merge only
     *   consumes `extends`-declared packs.
     * - `extends-only`: declared in `extends` but not installed
     *   (`require.resolve` failed). Skipped because the engine cannot
     *   load it.
     * - `not-a-pack`: present somewhere but doesn't expose a `register`
     *   callback (default export or named `register` function). Skipped
     *   because pack-discovery would throw on first attempt.
     */
    readonly reason: 'dep-only' | 'extends-only' | 'not-a-pack';
}
export interface PackResolutionResult {
    /** Packs that landed in the manifest (sorted by name). */
    readonly resolved: InstalledPacksManifest['packs'];
    /** Per-pack warnings for the consumer (sorted by name). */
    readonly warnings: readonly PackResolutionWarning[];
}
export interface ResolveInstalledPacksInput {
    /** Project root (where `package.json` lives). */
    readonly projectRoot: string;
    /** Loaded totem config (read for `extends`). */
    readonly config: TotemConfig;
    /**
     * Optional override for the package.json read. Tests pass a synthetic
     * dependencies map; production callers leave it undefined and the
     * function reads `<projectRoot>/package.json`.
     */
    readonly packageJsonDeps?: Readonly<Record<string, string>>;
    /**
     * Optional override for the require resolver. Tests stub this to
     * resolve fixture packs without writing to `node_modules`; production
     * callers use the default which delegates to `createRequire`.
     */
    readonly resolvePackPath?: (name: string, fromDir: string) => string | undefined;
}
/**
 * Compute the deduplicated union of `package.json` `@mmnto/pack-*` deps
 * and `totem.config.ts` `extends` entries. Returns the manifest payload
 * shape ready for `installed-packs.json` plus per-pack warnings for any
 * surface mismatch.
 *
 * Pure function — no filesystem write. The CLI integration calls
 * `writeInstalledPacksManifest()` to persist.
 */
export declare function resolveInstalledPacks(input: ResolveInstalledPacksInput): PackResolutionResult;
/**
 * Atomically write `<totemDir>/installed-packs.json` with the given
 * manifest payload. Mirrors `writeReviewExtensionsFile` semantics: temp
 * file + rename so a concurrent boot-time read sees the old or new
 * contents, never a partial write.
 *
 * Stamps the `cohort` field with the running `@mmnto/totem` version
 * via `resolveEngineVersion()` when the caller has not pre-populated
 * one (mmnto-ai/totem#1811). Tests pass an explicit cohort to override
 * the stamp.
 */
export declare function writeInstalledPacksManifest(totemDirAbs: string, manifest: InstalledPacksManifest): string;
//# sourceMappingURL=pack-manifest-writer.d.ts.map