// engine/universal-rules/installer.ts — SPEC-779
// Install all applicable universal rules for a given host.
import { join } from 'node:path';
import { atomicWriteFile } from '../safety/atomic-write-file.js';
import { UNIVERSAL_RULES } from './catalog.js';
import { writeRuleForHost } from './host-writer.js';
import { hashContent, readManifest, upsertManifestEntry } from './user-edit-detector.js';
/** Path of the manifest relative to projectPath. */
function manifestPath(projectPath, host) {
    if (host === 'claude-code') {
        return join(projectPath, '.claude', 'rules', '.planu-rules-manifest.json');
    }
    if (host === 'gemini') {
        return join(projectPath, '.gemini', '.planu-rules-manifest.json');
    }
    return join(projectPath, '.planu', 'rules-manifest.codex.json');
}
/**
 * Install all default-enabled universal rules applicable to `host`.
 * Idempotent: already-installed rules are skipped (manifest tracks hashes).
 * Returns the list of rules that were written.
 */
export async function installUniversalRules(projectPath, host) {
    const mPath = manifestPath(projectPath, host);
    const manifest = (await readManifest(mPath)) ?? { rules: [] };
    const installed = [];
    for (const rule of UNIVERSAL_RULES) {
        if (!rule.defaultEnabled) {
            continue;
        }
        const isApplicable = rule.applicableHosts.includes('all') || rule.applicableHosts.includes(host);
        if (!isApplicable) {
            continue;
        }
        try {
            const writtenPath = await writeRuleForHost(rule, projectPath, host);
            const content = rule.buildContent(host);
            const hash = hashContent(content);
            const entry = {
                id: rule.id,
                path: writtenPath,
                hostId: host,
                hashAtInstall: hash,
                installedAt: new Date().toISOString(),
            };
            const updated = upsertManifestEntry(manifest, entry);
            // Update manifest in-memory so successive rules see the latest state
            manifest.rules = updated.rules;
            installed.push({ id: rule.id, path: writtenPath, host, hash });
        }
        catch {
            // Best-effort: skip failing rules, don't abort the whole installation
        }
    }
    // Persist manifest atomically
    try {
        await atomicWriteFile(mPath, JSON.stringify(manifest, null, 2), { _skipFreezeCheck: true });
    }
    catch {
        // Non-fatal: manifest write failure doesn't undo the written rules
    }
    return installed;
}
//# sourceMappingURL=installer.js.map