"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generate = generate;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const constants_1 = require("./constants");
const template_engine_1 = require("./template-engine");
const files_1 = require("./files");
const languages_1 = require("./languages");
const logger = __importStar(require("./logger"));
function getTemplatesDir() {
    return path.join(__dirname, '..', 'templates');
}
function readTemplate(templatePath) {
    const fullPath = path.join(getTemplatesDir(), templatePath);
    if (!fs.existsSync(fullPath)) {
        throw new Error(`Template not found: ${templatePath}`);
    }
    return fs.readFileSync(fullPath, 'utf-8');
}
/**
 * Narrowed permission list for the dxkit-specific agent surface.
 * Carries only the binaries the six dxkit-* skills actually run:
 * git status/diff/log/branch (read-only inspection), the dxkit binary
 * itself (every analyzer / hook / baseline command), and the active
 * language packs' contributed commands (so the dxkit-action skill
 * can run `npm test` / `pytest` / etc. to verify a fix without
 * prompting on every step).
 *
 * Pre-2.5.1 the file carried Stop-hook noise about a `/learn` slash
 * command that no longer ships, plus conditional gcloud / pulumi /
 * docker entries tied to generic skills that also no longer ship.
 * Dropped here.
 */
function buildSettingsJson(config) {
    const perms = [
        'Bash(git status:*)',
        'Bash(git diff:*)',
        'Bash(git log:*)',
        'Bash(git branch:*)',
        'Bash(npx vyuh-dxkit:*)',
        'Bash(./node_modules/.bin/vyuh-dxkit:*)',
        'Bash(vyuh-dxkit:*)',
    ];
    for (const lang of (0, languages_1.activeLanguagesFromStack)(config)) {
        if (lang.permissions)
            perms.push(...lang.permissions);
    }
    return (JSON.stringify({
        $schema: 'https://json.schemastore.org/claude-code-settings.json',
        permissions: {
            allow: perms,
            deny: [],
        },
        // PreToolUse hook on code-search tools: injects a slim graph
        // subgraph as additional context so the agent needs fewer
        // follow-up whole-file reads (the navigation-layer token win).
        // ADDITIVE + FAIL-OPEN by construction — `context-hook` only
        // ever adds context and silently no-ops when graph.json is
        // absent/stale, so the search tool always works normally.
        hooks: {
            PreToolUse: [
                {
                    matcher: 'Grep|Glob',
                    hooks: [
                        {
                            type: 'command',
                            command: 'npx vyuh-dxkit context-hook',
                        },
                    ],
                },
            ],
        },
    }, null, 2) + '\n');
}
/**
 * The six dxkit-specific skills shipped under `--with-dxkit-agents`.
 * Each lives at `.claude/skills/<name>/SKILL.md` in the template dir;
 * generator copies them verbatim (no template substitution — the
 * skill content references the canonical `vyuh-dxkit` CLI surface
 * and doesn't need per-project variables).
 */
const DXKIT_SKILLS = [
    'dxkit-learn',
    'dxkit-init',
    'dxkit-config',
    'dxkit-hooks',
    'dxkit-reports',
    'dxkit-action',
    // dxkit-fix (2.5.2): reactive repair surface. Consumes
    // `vyuh-dxkit doctor --json` output and walks the customer through
    // each fixable check. Lands after the doctor pivot adds structured
    // output + fix metadata in 2.5.2.
    'dxkit-fix',
    // dxkit-update (2.5.2): existing-install upgrade orchestrator.
    // Consumes `vyuh-dxkit upgrade --plan --json` output and drives
    // conversational upgrade with version-delta analysis, warnings,
    // and per-step confirmation.
    'dxkit-update',
    // dxkit-onboard (2.5.2): fresh-install orchestrator. Walks the
    // customer through the full first-time setup journey (install,
    // doctor, fix-gaps, baseline, hooks, branch protection, prebuild).
    // Dispatches into the other lifecycle skills for sub-decisions.
    'dxkit-onboard',
    // dxkit-feature: forward-development orchestrator. Orients via the
    // code graph (context / explore) to find where a new feature plugs
    // in and what it touches, then runs the analyzers + guardrail on the
    // change so net-new development doesn't ship a regression. The
    // proactive counterpart to dxkit-action's reactive fix loop.
    'dxkit-feature',
    // dxkit-docs: documentation generator. Reads the Documentation
    // dimension's gaps, orients on the real code via the graph, and
    // writes grounded README / docstrings / API + architecture docs —
    // re-running the slop check so generated prose doesn't trade
    // Documentation score for Quality score.
    'dxkit-docs',
];
async function generate(targetDir, config, mode, force, _noScan = false, withDxkitAgents = false) {
    const variables = (0, constants_1.buildVariables)(config);
    const conditions = (0, constants_1.buildConditions)(config);
    const templatesDir = getTemplatesDir();
    const result = {
        created: [],
        skipped: [],
        overwritten: [],
        manifest: {
            version: constants_1.VERSION,
            mode,
            generatedAt: new Date().toISOString(),
            config,
            files: {},
        },
    };
    const opts = (evolving) => ({ force, evolving, skipIfExists: !force });
    function track(outputPath, content, writeResult, evolving) {
        const rel = path.relative(targetDir, outputPath);
        if (writeResult === 'created')
            result.created.push(rel);
        else if (writeResult === 'skipped')
            result.skipped.push(rel);
        else if (writeResult === 'overwritten')
            result.overwritten.push(rel);
        result.manifest.files[rel] = {
            hash: evolving ? null : content ? (0, files_1.sha256)(content) : null,
            evolving,
        };
    }
    async function writeTemplate(templatePath, outputRel, evolving = false) {
        const raw = readTemplate(templatePath);
        const processed = (0, template_engine_1.processTemplate)(raw, variables, conditions);
        const outputPath = path.join(targetDir, outputRel);
        const res = await (0, files_1.writeFile)(outputPath, processed, opts(evolving));
        track(outputPath, processed, res, evolving);
    }
    function copyStatic(templatePath, outputRel, evolving = false) {
        const srcPath = path.join(templatesDir, templatePath);
        if (!fs.existsSync(srcPath))
            return;
        const outputPath = path.join(targetDir, outputRel);
        const res = (0, files_1.copyFile)(srcPath, outputPath, opts(evolving));
        const content = evolving ? null : fs.readFileSync(srcPath, 'utf-8');
        track(outputPath, content, res, evolving);
    }
    if (withDxkitAgents) {
        logger.header('Generating dxkit agent context');
        // Open-standard project prose — read by every coding agent
        // (Claude / Codex / Cursor / Aider). Pre-2.5.1 this content lived
        // in CLAUDE.md; AGENTS.md is the cross-platform replacement.
        await writeTemplate('AGENTS.md.template', 'AGENTS.md');
        logger.success('AGENTS.md');
        // CLAUDE.md becomes a small shim that points at AGENTS.md. Claude
        // Code reads both at session start; the shim carries Claude-
        // specific config (skill list, rules pointer) and defers shared
        // context to AGENTS.md.
        await writeTemplate('CLAUDE.md.template', 'CLAUDE.md');
        logger.success('CLAUDE.md');
        // Narrowed settings.json — drops the Stop-hook noise + conditional
        // gcloud/pulumi/docker entries that referenced generic skills that
        // no longer ship.
        const settingsContent = buildSettingsJson(config);
        const settingsPath = path.join(targetDir, '.claude', 'settings.json');
        const settingsRes = await (0, files_1.writeFile)(settingsPath, settingsContent, opts(false));
        track(settingsPath, settingsContent, settingsRes, false);
        logger.success('.claude/settings.json');
        // The six dxkit-specific skills. Each ships as a single SKILL.md
        // under `.claude/skills/dxkit-<name>/`. Auto-discovered by Claude
        // Code via skill frontmatter (`name` + `description`).
        for (const skill of DXKIT_SKILLS) {
            copyStatic(`.claude/skills/${skill}/SKILL.md`, `.claude/skills/${skill}/SKILL.md`);
        }
        logger.success('.claude/skills/dxkit-*');
        // Per-language rules from each active pack — still useful as
        // contextual hints to any agent (coding conventions, lint rule
        // exceptions, etc.).
        for (const lang of (0, languages_1.activeLanguagesFromStack)(config)) {
            if (lang.ruleFile) {
                copyStatic(`.claude/rules/${lang.ruleFile}`, `.claude/rules/${lang.ruleFile}`);
            }
        }
        // Framework-specific rules — NOT pack-owned. Frameworks
        // (nextjs/loopback/express) live under the top-level `framework`
        // signal, not in `languages`. Stay hardcoded here until a
        // framework-pack abstraction exists.
        if (conditions.IF_NEXTJS)
            copyStatic('.claude/rules/nextjs.md', '.claude/rules/nextjs.md');
        if (config.framework === 'loopback')
            copyStatic('.claude/rules/loopback.md', '.claude/rules/loopback.md');
        if (config.framework === 'express')
            copyStatic('.claude/rules/express.md', '.claude/rules/express.md');
        logger.success('.claude/rules/');
    }
    // Always write the manifest — `vyuh-dxkit update` / `doctor` / etc.
    // read it to know what was configured even when no agent scaffold
    // is present.
    const manifestContent = JSON.stringify(result.manifest, null, 2) + '\n';
    fs.mkdirSync(targetDir, { recursive: true });
    fs.writeFileSync(path.join(targetDir, '.vyuh-dxkit.json'), manifestContent, 'utf-8');
    return result;
}
//# sourceMappingURL=generator.js.map