#!/usr/bin/env node
// Copyright (c) 2026 Hellmai Ltd
// SPDX-License-Identifier: AGPL-3.0-only
/**
 * @file lumenflow-file-classifier.ts
 * Shared file manifest for LumenFlow-generated integration artifacts (WU-2590).
 *
 * This module is the single source of truth for "which files does LumenFlow
 * generate on a user's project?" It powers both `lumenflow:disable` and
 * `lumenflow:uninstall`, and it explicitly reuses the same constants that
 * `commands/integrate.ts` uses (`CLAUDE_HOOKS.SCRIPTS`, `DIRECTORIES`,
 * `LUMENFLOW_CLIENT_IDS`) so there is exactly one source of truth for the
 * integration file set.
 *
 * Adding a new generated file? Add it to one of the `collect*()` functions
 * below. Do NOT maintain a parallel list anywhere else.
 */
import * as fs from 'node:fs';
import * as path from 'node:path';
import { CLAUDE_HOOKS, DIRECTORIES, LUMENFLOW_CLIENT_IDS } from '@lumenflow/core';
/**
 * Collect Claude Code hook scripts that `integrate.ts` generates.
 */
function collectClaudeHooks(projectDir) {
    const hookScripts = Object.values(CLAUDE_HOOKS.SCRIPTS);
    const out = [];
    for (const script of hookScripts) {
        const rel = path.join(DIRECTORIES.CLAUDE_HOOKS, script);
        if (fs.existsSync(path.join(projectDir, rel))) {
            out.push({
                path: rel,
                category: 'hook',
                client: LUMENFLOW_CLIENT_IDS.CLAUDE_CODE,
            });
        }
    }
    return out;
}
/**
 * The Claude Code settings.json may contain user-authored content alongside
 * the LumenFlow-managed `hooks` section.
 */
function collectClaudeSettings(projectDir) {
    const rel = path.join(DIRECTORIES.CLAUDE, 'settings.json');
    if (!fs.existsSync(path.join(projectDir, rel)))
        return [];
    return [
        {
            path: rel,
            category: 'settings',
            client: LUMENFLOW_CLIENT_IDS.CLAUDE_CODE,
            surgicalStrip: true,
        },
    ];
}
/**
 * Cursor recovery rules generated by `integrateCursor`.
 */
function collectCursorRules(projectDir) {
    const rel = path.join('.cursor', 'rules', 'lumenflow-recovery.md');
    if (!fs.existsSync(path.join(projectDir, rel)))
        return [];
    return [
        {
            path: rel,
            category: 'vendor-rule',
            client: LUMENFLOW_CLIENT_IDS.CURSOR,
        },
    ];
}
/**
 * Codex CLI integration appends a section to AGENTS.md.
 */
function collectCodexAgents(projectDir) {
    const rel = 'AGENTS.md';
    const abs = path.join(projectDir, rel);
    if (!fs.existsSync(abs))
        return [];
    // Only report surgical strip if the marker section exists
    const content = fs.readFileSync(abs, 'utf-8');
    if (!content.includes('## Context Recovery (WU-2157)'))
        return [];
    return [
        {
            path: rel,
            category: 'docs',
            client: LUMENFLOW_CLIENT_IDS.CODEX_CLI,
            surgicalStrip: true,
        },
    ];
}
/**
 * Core enforcement delegators generated by `syncCoreEnforcementDelegators`.
 */
function collectCoreDelegators(projectDir) {
    const out = [];
    const candidates = [
        { path: path.join('.husky', 'pre-commit'), category: 'hook' },
        {
            path: path.join('.github', 'workflows', 'lumenflow-ci.yml'),
            category: 'ci',
        },
    ];
    for (const c of candidates) {
        if (fs.existsSync(path.join(projectDir, c.path))) {
            out.push({ path: c.path, category: c.category });
        }
    }
    return out;
}
/**
 * State, stamps, and history surfaces.
 */
function collectStateAndHistory(projectDir) {
    const out = [];
    const surfaces = [
        { path: '.lumenflow/state', category: 'state' },
        { path: '.lumenflow/stamps', category: 'stamp', keepWithHistory: true },
        { path: '.lumenflow/constraints.md', category: 'config', keepWithConfig: true },
        { path: 'docs/operations/tasks/wu', category: 'docs', keepWithHistory: true },
        { path: 'workspace.yaml', category: 'config', keepWithConfig: true },
    ];
    for (const s of surfaces) {
        if (fs.existsSync(path.join(projectDir, s.path))) {
            out.push(s);
        }
    }
    return out;
}
/**
 * Return the full list of LumenFlow-generated files in a project.
 *
 * This is the canonical manifest. Both `lumenflow:disable` and
 * `lumenflow:uninstall` consume this — do not duplicate the logic elsewhere.
 */
export function getGeneratedFileManifest(projectDir, opts = {}) {
    const all = [
        ...collectClaudeHooks(projectDir),
        ...collectClaudeSettings(projectDir),
        ...collectCursorRules(projectDir),
        ...collectCodexAgents(projectDir),
        ...collectCoreDelegators(projectDir),
        ...collectStateAndHistory(projectDir),
    ];
    if (!opts.client)
        return all;
    // Scope: include client-specific files plus non-client-scoped state/config.
    return all.filter((f) => !f.client || f.client === opts.client);
}
export function filterForUninstall(files, opts = {}) {
    return files.filter((f) => {
        if (opts.keepHistory && f.keepWithHistory)
            return false;
        if (opts.keepConfig && f.keepWithConfig)
            return false;
        return true;
    });
}
//# sourceMappingURL=lumenflow-file-classifier.js.map