"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.registryHealthRules = void 0;
const path = __importStar(require("path"));
const PROJECT_TYPES = ["nextjs", "turbo", "node"];
function diag(rule, filePath, message, opts = {}) {
    return {
        ruleId: rule.id,
        filePath,
        severity: rule.severity,
        message,
        help: opts.help || rule.help,
        autoFixable: opts.autoFixable ?? false,
    };
}
const registryExists = {
    id: "registry/manifest-exists",
    name: "Registry Manifest Exists",
    category: "node",
    severity: "error",
    description: "Verify that .mycontext/file-registry.json exists",
    help: "Run 'mycontext registry:update' to generate the file registry",
    appliesTo: PROJECT_TYPES,
    async check(ctx) {
        const results = [];
        const registryPath = ".mycontext/file-registry.json";
        if (!(await ctx.fileExists(registryPath))) {
            results.push(diag(this, registryPath, "File registry is missing — no file-level tracking is active", { autoFixable: true }));
        }
        return results;
    },
    async fix(_ctx, _diag) {
        return false;
    },
};
const strictCoverage = {
    id: "registry/strict-coverage",
    name: "Strict File Coverage",
    category: "node",
    severity: "warning",
    description: "All source files must be tracked in file-registry.json (no untracked files)",
    help: "Run 'mycontext registry:update' to refresh, then review untracked files and add them to context.json",
    appliesTo: PROJECT_TYPES,
    async check(ctx) {
        const results = [];
        const registryPath = ".mycontext/file-registry.json";
        const registry = await ctx.readJson(registryPath);
        if (!registry || !registry.files) {
            results.push(diag(this, registryPath, "Cannot check coverage: registry missing or malformed"));
            return results;
        }
        const sourceExts = new Set([
            ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs",
            ".json", ".yaml", ".yml", ".toml",
            ".css", ".scss", ".less",
            ".md", ".mdx", ".graphql", ".prisma",
        ]);
        let untrackedCount = 0;
        const untrackedFiles = [];
        for (const [filePath, entry] of Object.entries(registry.files)) {
            const ext = path.extname(filePath).toLowerCase();
            if (!sourceExts.has(ext))
                continue;
            if (entry.status === "untracked") {
                untrackedCount++;
                if (untrackedFiles.length < 10)
                    untrackedFiles.push(filePath);
            }
        }
        if (untrackedCount > 0) {
            const sample = untrackedFiles.join(", ");
            results.push(diag(this, registryPath, `${untrackedCount} untracked source file(s) — add these to context.json or mark ignored: ${sample}${untrackedCount > 10 ? ` +${untrackedCount - 10} more` : ""}`));
        }
        return results;
    },
};
const ownershipDrift = {
    id: "registry/ownership-drift",
    name: "Ownership Path Drift",
    category: "node",
    severity: "warning",
    description: "Paths referenced in context.json feature ownership must exist on disk",
    help: "Update context.json to remove stale paths, or create the missing files",
    appliesTo: PROJECT_TYPES,
    async check(ctx) {
        const results = [];
        const brainPath = ".mycontext/context.json";
        const brain = await ctx.readJson(brainPath);
        if (!brain)
            return results;
        const features = brain.features || [];
        for (const feature of features) {
            const ownership = feature.ownership || {};
            for (const key of ["routes", "components", "actions", "models", "permissions", "i18n", "tests"]) {
                const paths = ownership[key] || [];
                for (const p of paths) {
                    const cleaned = p.replace(/^\//, "");
                    if (!(await ctx.fileExists(cleaned))) {
                        results.push(diag(this, brainPath, `Feature "${feature.name}" references missing path "${cleaned}" in ownership.${key}`));
                    }
                }
            }
        }
        return results;
    },
};
exports.registryHealthRules = [
    registryExists,
    strictCoverage,
    ownershipDrift,
];
//# sourceMappingURL=registry-health-rules.js.map