/**
 * studiograph admin migrate-assets — one-time re-key of legacy asset URLs.
 *
 * Rewrites every legacy `/api/assets/{type}/{id}/{filename}` reference (in
 * entity bodies AND `asset_url` frontmatter) to the immutable-key scheme
 * `/api/assets/{assetId}/{filename}`, copying the blob old→new and recording
 * authoritative ownership in assets.db. After this runs (and the legacy route
 * is dropped), renaming/retyping an entity can never orphan its images.
 *
 * Safety:
 *   - `--dry-run` (default OFF): reports counts + missing blobs, writes nothing.
 *   - Idempotent: a `migration_ledger` keyed by (repo, oldKey) means a re-run
 *     reuses the same assetId (no duplicate blobs). New-scheme (2-segment) URLs
 *     never match the extractor, so already-migrated content is skipped.
 *   - Refuses if a target repo has uncommitted changes (catches half-edits).
 *   - Copies (never moves) blobs, so the legacy route keeps serving until the
 *     separate old-blob cleanup step runs. Missing source blobs are reported
 *     and their URL left legacy (rewriting would just relocate the 404).
 *   - One commit per repo.
 *
 * This is code only — running it against production is a deliberate, backed-up
 * step (see ~/.claude/plans/rename-carries-assets.md §6).
 */
import { Command } from 'commander';
import { type AssetService } from '../../../services/assets/index.js';
import type { AssetIndexService } from '../../../services/assets/asset-index-service.js';
export interface AssetMigrationReport {
    totalUrls: number;
    migrated: number;
    missing: number;
    filesChanged: number;
    missingKeys: string[];
}
export interface AssetMigrationDeps {
    cwd: string;
    repos: Array<{
        name: string;
        path: string;
    }>;
    assetService: AssetService;
    assetIndex: AssetIndexService;
    dryRun: boolean;
    /** Per-repo commit hook (omit in dry-run / tests). */
    commit?: (repoName: string, message: string) => void;
    /** Progress callback (spinner in the CLI). */
    onRepo?: (repoName: string, changedFiles: number) => void;
}
/**
 * Core migration loop — decoupled from clack/Workspace so it's unit-testable
 * with a real local AssetService + AssetIndexService over a temp workspace.
 */
export declare function runAssetMigration(deps: AssetMigrationDeps): Promise<AssetMigrationReport>;
export declare const adminMigrateAssetsCommand: Command;
