/**
 * `olam worldspec compile <path>... [--out <dir>] [--no-digests]` —
 * compile one or more worldspec YAMLs into a deterministic execution-
 * graph.json + lockfile.json. v1 SEAM contract per Decision #9.
 *
 * Multiple paths layer in argument order (later overrides earlier);
 * matches plan body's "per-project default + orchestrator (highest
 * priority) + task-level overrides" pattern.
 *
 * `--no-digests` skips Docker subprocess invocations (writes <digest-
 * pending> sentinels). Useful for: dry-run validation, CI environments
 * where Docker isn't available, deterministic-output tests.
 *
 * Defaults output to `./compiled/{execution-graph,lockfile}.json` if
 * --out is provided; otherwise prints execution-graph to stdout (for
 * piping / inspection).
 */
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import { resolve as resolvePath } from 'node:path';
import YAML from 'yaml';
import { canonicalStringify, compileWorldspec, dockerDigestResolver, resolveDigests, WorldspecSchema, } from '@olam/core/src/worldspec/index.js';
import { EXIT_DIGEST_UNRESOLVED, EXIT_GENERIC_ERROR, EXIT_WORLDSPEC_FILE_NOT_FOUND, EXIT_WORLDSPEC_INVALID, } from '../../exit-codes.js';
import { printError, printSuccess } from '../../output.js';
export function registerWorldspecCompile(parent) {
    parent
        .command('compile <path...>')
        .description('Compile worldspec YAMLs into a deterministic execution-graph + lockfile')
        .option('--out <dir>', 'Write artifacts to <dir>/{execution-graph,lockfile}.json')
        .option('--no-digests', 'Skip Docker digest resolution (emits <digest-pending> sentinels)')
        .option('--allow-pending-digests', 'Continue with <digest-pending> sentinels if Docker digest resolution fails (CI / dry-run); without this flag, digest failure exits 23 to preserve Decision #13 fail-fast invariant', false)
        .action(async (paths, opts) => {
        // Step 1: load + validate each worldspec
        const specs = [];
        const sourcePolicies = [];
        for (const p of paths) {
            const abs = resolvePath(process.cwd(), p);
            if (!existsSync(abs)) {
                printError(`worldspec not found at ${abs}`);
                process.exit(EXIT_WORLDSPEC_FILE_NOT_FOUND);
            }
            let yaml;
            try {
                yaml = YAML.parse(readFileSync(abs, 'utf8'));
            }
            catch (err) {
                printError(`${p}: YAML parse error: ${err.message}`);
                process.exit(EXIT_WORLDSPEC_INVALID);
            }
            const parsed = WorldspecSchema.safeParse(yaml);
            if (!parsed.success) {
                printError(`${p}: schema violation — run 'olam worldspec validate ${p}' for details`);
                process.exit(EXIT_WORLDSPEC_INVALID);
            }
            specs.push(parsed.data);
            sourcePolicies.push(p);
        }
        // Step 2: read package version (compilerVersion in execution-graph)
        const compilerVersion = `@pleri/olam-cli@${getPkgVersion()}`;
        // Step 3: compile (synchronous; <50ms target)
        let result;
        try {
            result = compileWorldspec(specs, {
                compilerVersion,
                sourcePolicies,
            });
        }
        catch (err) {
            printError(`compile failed: ${err.message}`);
            process.exit(EXIT_GENERIC_ERROR);
        }
        // Step 4: optionally resolve digests via Docker.
        // MEDIUM fix (A6 CP3 2026-05-09): default behaviour now FAILS FAST
        // when digest resolution fails. Decision #13 says lockfile records
        // sha256 for fail-fast at world-spawn; silently committing
        // <digest-pending> regresses that invariant. Operators who want
        // dry-run / no-Docker CI explicitly opt in via --allow-pending-digests.
        let lockfile = result.lockfile;
        if (opts.digests !== false) {
            try {
                lockfile = await resolveDigests(lockfile, dockerDigestResolver);
            }
            catch (err) {
                if (opts.allowPendingDigests) {
                    process.stderr.write(`warn: digest resolution failed (${err.message}); ` +
                        `lockfile will contain <digest-pending> sentinels per --allow-pending-digests. ` +
                        `Re-compile with Docker reachable to populate digests before relying on world-spawn fail-fast.\n`);
                }
                else {
                    printError(`digest resolution failed: ${err.message}\n` +
                        `Lockfile cannot fail-fast on tampered images without sha256 records (Decision #13).\n` +
                        `Resolutions:\n` +
                        `  • Ensure Docker is running + image is locally present (\`docker pull\`)\n` +
                        `  • Or pass --allow-pending-digests to opt INTO <digest-pending> sentinels (CI / dry-run)\n` +
                        `  • Or pass --no-digests to skip resolution entirely`);
                    process.exit(EXIT_DIGEST_UNRESOLVED);
                }
            }
        }
        // Step 5: emit
        const graphJson = canonicalStringify(result.executionGraph);
        const lockfileJson = canonicalStringify(lockfile);
        if (opts.out) {
            const outDir = resolvePath(process.cwd(), opts.out);
            try {
                mkdirSync(outDir, { recursive: true });
                writeFileSync(resolvePath(outDir, 'execution-graph.json'), graphJson, 'utf8');
                writeFileSync(resolvePath(outDir, 'lockfile.json'), lockfileJson, 'utf8');
                printSuccess(`wrote execution-graph + lockfile to ${outDir}`);
            }
            catch (err) {
                printError(`failed to write ${outDir}: ${err.message}`);
                process.exit(EXIT_GENERIC_ERROR);
            }
        }
        else {
            // Stdout: just the execution-graph (lockfile suppressed; use --out for both)
            process.stdout.write(graphJson);
        }
        process.exit(0);
    });
}
function getPkgVersion() {
    // v1: static fallback. The CLI's actual version comes from its
    // package.json at publish time; for execution-graph.compilerVersion
    // the static value is sufficient (deterministic-output tests need a
    // stable version string anyway). Phase B may wire dynamic version
    // injection at bundle time.
    return '0.2.0';
}
//# sourceMappingURL=compile.js.map