/**
 * olam skills 10x — sub-namespace for managing the /10x: planning chain
 * skills + beads (bd) integration.
 *
 *   olam skills 10x install [--no-beads]   Sync chain skills via existing
 *                                          syncSkills() machinery + auto-
 *                                          bootstrap beads.
 *   olam skills 10x uninstall              Remove /10x: chain skill symlinks.
 *   olam skills 10x doctor                 Health probe: chain skill presence
 *                                          + beads CLI + beads project init +
 *                                          beads Claude hooks.
 *   olam skills 10x version                Show olam-cli version + registered
 *                                          skill source identities.
 *
 * Per Pass 3.1 scope-reduction (olam-harness-flywheel.md): this is a thin
 * wrapper over the existing `olam skills` surface (skills.ts, skills-hook.ts,
 * skills-doctor.ts). The 10x sub-namespace gives /10x: chain skills their own
 * verb without colliding with `olam install` (which provisions worlds, not
 * skills).
 */
import { execFileSync } from 'node:child_process';
import * as fs from 'node:fs';
import * as path from 'node:path';
import { syncSkills, listSkillSources, claudeDir, } from '@olam/core/src/skill-sources/index.js';
import { readCliVersion } from '../cli-version.js';
import { printError, printSuccess, printWarning } from '../output.js';
const CHAIN_SKILL_NAMES = [
    '10x:brainstorm',
    '10x:plan-hard',
    '10x:review-plan',
    '10x:break-plan',
    '10x:commit-plan',
    '10x:execute',
    '10x:retro',
    '10x:learn',
];
function asMessage(err) {
    return err instanceof Error ? err.message : String(err);
}
function hasBeadsCli() {
    try {
        execFileSync('bd', ['--version'], { stdio: 'ignore' });
        return true;
    }
    catch {
        return false;
    }
}
function hasBeadsProjectInit(cwd) {
    return fs.existsSync(path.join(cwd, '.beads'));
}
function hasBeadsClaudeSetup() {
    const settingsPath = path.join(claudeDir(), 'settings.json');
    if (!fs.existsSync(settingsPath))
        return false;
    try {
        const content = fs.readFileSync(settingsPath, 'utf8');
        // Sentinel detection: `bd setup claude` writes hook entries whose
        // `command` field invokes the `bd` binary directly. Look for a
        // specific shape rather than the word `bd` anywhere — the looser
        // form false-positives on user comments, paths, or unrelated tokens
        // (CP3 audit S-LOW finding).
        return /"command"\s*:\s*"bd\b/.test(content) || /"bd setup\b/.test(content);
    }
    catch {
        return false;
    }
}
async function bootstrapBeads(cwd) {
    if (!hasBeadsCli()) {
        printWarning('beads CLI (bd) not installed — skipping bd auto-bootstrap. Install: brew install beads OR npm i -g @beads/bd');
        return;
    }
    if (!hasBeadsProjectInit(cwd)) {
        console.log('bd init — initializing beads in current project');
        try {
            execFileSync('bd', ['init', '--quiet', '--stealth'], {
                cwd,
                stdio: 'inherit',
            });
        }
        catch (err) {
            printWarning(`bd init failed (continuing): ${asMessage(err)}`);
        }
    }
    else {
        console.log('beads project already initialized — skipping bd init');
    }
    if (!hasBeadsClaudeSetup()) {
        console.log('bd setup claude — installing beads Claude Code hooks');
        try {
            execFileSync('bd', ['setup', 'claude'], { cwd, stdio: 'inherit' });
        }
        catch (err) {
            printWarning(`bd setup claude failed (continuing): ${asMessage(err)}`);
        }
    }
    else {
        console.log('beads Claude hooks already installed — skipping bd setup');
    }
}
function captureSourceShas() {
    return listSkillSources().map((s) => ({
        id: s.id,
        name: s.name,
        sha: s.lastPulledSha,
    }));
}
function diffSourceShas(before, after) {
    const beforeMap = new Map(before.map((s) => [s.id, s]));
    const bumps = [];
    for (const post of after) {
        const pre = beforeMap.get(post.id);
        if (!pre || pre.sha !== post.sha) {
            bumps.push({
                id: post.id,
                name: post.name,
                from: pre?.sha,
                to: post.sha,
            });
        }
    }
    return bumps;
}
function shortSha(sha) {
    if (!sha)
        return '<none>';
    return sha.slice(0, 8);
}
function listInstalledClaudeSkills() {
    const skillsDir = path.join(claudeDir(), 'skills');
    if (!fs.existsSync(skillsDir))
        return [];
    try {
        return fs.readdirSync(skillsDir).filter((name) => {
            try {
                const stat = fs.lstatSync(path.join(skillsDir, name));
                return stat.isSymbolicLink() || stat.isDirectory();
            }
            catch {
                return false;
            }
        });
    }
    catch {
        return [];
    }
}
function isChainSkill(name) {
    // Tolerant match: chain skills may land as `10x:brainstorm`, `brainstorm`,
    // or `10x-brainstorm` depending on source-side naming. Speculative
    // `endsWith(':${slug}')` branch dropped — no source emits it (CP3 audit
    // S-LOW finding); add back when a real consumer is identified.
    const lower = name.toLowerCase();
    return CHAIN_SKILL_NAMES.some((canonical) => {
        const slug = canonical.replace(/^10x:/, '');
        return (lower === canonical.toLowerCase() ||
            lower === slug ||
            lower === `10x-${slug}`);
    });
}
export function registerSkills10x(program) {
    const skills = program.commands.find((c) => c.name() === 'skills') ??
        program.command('skills').description('Manage skill sources and synchronization');
    const tenx = skills
        .command('10x')
        .description('Manage the /10x: planning chain skills + beads integration');
    tenx
        .command('install')
        .description('Sync /10x: chain skills from registered sources + auto-bootstrap beads (bd init + bd setup claude). Surfaces source-SHA bumps + shadow-backups for sentinel-versioned upgrade.')
        .option('--no-beads', 'Skip beads auto-bootstrap (chain skills only)')
        .option('--force', 'Suppress shadow-backup warning + proceed without operator attention (shadow backups are still created by the sync engine; this flag only suppresses the surface-prominence)')
        .action(async (opts) => {
        try {
            // A2 — capture pre-sync SHAs to detect canonical-version bumps
            // after sync completes.
            const preSync = captureSourceShas();
            console.log('Syncing /10x: chain skills from registered sources...');
            const summary = await syncSkills({});
            printSuccess(`Synced ${summary.artifactCount} artifact(s) from ${summary.sourceCount} source(s)`);
            // A2 — surface canonical-version bumps (lastPulledSha changes).
            const postSync = captureSourceShas();
            const bumps = diffSourceShas(preSync, postSync);
            if (bumps.length > 0) {
                console.log('');
                console.log(`Canonical-version bumps detected (${bumps.length}):`);
                for (const b of bumps) {
                    console.log(`  ${b.name}: ${shortSha(b.from)} → ${shortSha(b.to)}`);
                }
            }
            // A2 — surface shadow-backups. These are created by the sync engine
            // whenever a non-symlink (locally-edited) file would be overwritten.
            // Operator attention required unless --force.
            const shadowBackups = summary.deploy?.shadowBackups ?? [];
            if (shadowBackups.length > 0 && !opts.force) {
                printWarning(`${shadowBackups.length} shadow backup(s) created — local edits preserved at .pre-sync-* paths:`);
                for (const p of shadowBackups)
                    console.log(`    ${p}`);
                console.log('  Review backups; re-run with --force to suppress this warning.');
            }
            else if (shadowBackups.length > 0 && opts.force) {
                console.log(`--force — ${shadowBackups.length} shadow backup(s) created silently`);
            }
            if (opts.beads !== false) {
                await bootstrapBeads(process.cwd());
            }
            else {
                console.log('--no-beads — skipping beads auto-bootstrap');
            }
            printSuccess('olam skills 10x install complete');
            console.log('Verify with: olam skills 10x doctor');
        }
        catch (err) {
            printError(`Install failed: ${asMessage(err)}`);
            process.exitCode = 1;
        }
    });
    tenx
        .command('uninstall')
        .description('Remove /10x: chain skill symlinks from ~/.claude/skills (preserves user-authored skills + non-chain skill sources)')
        .action(() => {
        const skillsDir = path.join(claudeDir(), 'skills');
        if (!fs.existsSync(skillsDir)) {
            printWarning('No ~/.claude/skills/ directory found; nothing to uninstall');
            return;
        }
        let removed = 0;
        for (const name of fs.readdirSync(skillsDir)) {
            const full = path.join(skillsDir, name);
            try {
                const stat = fs.lstatSync(full);
                if (!stat.isSymbolicLink())
                    continue;
                const target = fs.readlinkSync(full);
                // Only unlink symlinks whose name OR target path identifies them
                // as /10x: chain skills. Conservative: leave non-chain symlinks alone.
                if (isChainSkill(name) || /\/10x[-:]/.test(target)) {
                    fs.unlinkSync(full);
                    removed += 1;
                }
            }
            catch {
                // ignore
            }
        }
        printSuccess(`Removed ${removed} /10x: chain skill symlink(s)`);
        console.log('User-authored + non-chain skill sources preserved');
    });
    tenx
        .command('doctor')
        .description('Diagnose /10x: chain skill installation + beads bootstrap state')
        .action(() => {
        console.log('=== /10x: chain skills + beads health ===');
        const installed = listInstalledClaudeSkills();
        const chainInstalled = installed.filter(isChainSkill);
        console.log(`  /10x: chain skills:     ${chainInstalled.length} / ${CHAIN_SKILL_NAMES.length} installed`);
        for (const canonical of CHAIN_SKILL_NAMES) {
            const slug = canonical.replace(/^10x:/, '');
            const found = installed.some((n) => n.toLowerCase() === canonical.toLowerCase() ||
                n.toLowerCase() === slug ||
                n.toLowerCase() === `10x-${slug}`);
            console.log(`    ${found ? '✓' : '✗'} ${canonical}`);
        }
        const bdCli = hasBeadsCli();
        const bdInit = hasBeadsProjectInit(process.cwd());
        const bdHooks = hasBeadsClaudeSetup();
        console.log(`  beads CLI installed:    ${bdCli ? '✓' : '✗'}`);
        console.log(`  beads project init:     ${bdInit ? '✓' : '✗'} (cwd)`);
        console.log(`  beads Claude hooks:     ${bdHooks ? '✓' : '✗'}`);
        const allChainPresent = chainInstalled.length === CHAIN_SKILL_NAMES.length;
        const allOk = allChainPresent && bdCli && bdInit && bdHooks;
        if (allOk) {
            printSuccess('All /10x: chain skill + beads checks pass');
            return;
        }
        const fixHints = [];
        if (!allChainPresent)
            fixHints.push('olam skills 10x install');
        if (!bdCli)
            fixHints.push('brew install beads OR npm i -g @beads/bd');
        if (!bdInit)
            fixHints.push('bd init');
        if (!bdHooks)
            fixHints.push('bd setup claude');
        printWarning('Some checks failed. Remediate via:');
        for (const hint of fixHints)
            console.log(`    $ ${hint}`);
        process.exitCode = 1;
    });
    tenx
        .command('version')
        .description('Show olam-cli version + registered chain-skill source identities')
        .action(() => {
        const olamVersion = readCliVersion();
        const sources = listSkillSources();
        console.log(`olam-cli:           ${olamVersion}`);
        console.log(`chain canonical:    ${CHAIN_SKILL_NAMES.length} skills (/10x: chain)`);
        console.log(`registered sources: ${sources.length}`);
        for (const s of sources) {
            const shortId = s.id ? s.id.slice(0, 8) : '????????';
            console.log(`  [${shortId}]  ${s.name}  ${s.gitUrl}#${s.branch}`);
        }
        if (sources.length === 0) {
            printWarning('No skill sources registered. Add one via: olam skills source add <url>');
        }
    });
}
//# sourceMappingURL=skills-10x.js.map