// engine/validator/scope-resolver.ts — SPEC-730
// Pure function that resolves which holistic dimensions apply to a given spec
// based on its target x scope combination. No side effects.
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const ALL_DIMENSIONS = [
    'tests',
    'lint',
    'typecheck',
    'security-scan',
    'spec-compliance',
];
/**
 * Targets that are considered "meta" in nature: they own infrastructure,
 * configuration or shared concerns — not primary source code.
 * For these targets, lint and tests do not apply unless the scope is `feature`.
 */
const META_LIKE_TARGETS = new Set([
    'infrastructure',
    'database',
    'shared',
]);
// ---------------------------------------------------------------------------
// Core resolver
// ---------------------------------------------------------------------------
/**
 * Resolves which holistic dimensions apply to the given spec.
 *
 * Rules (in priority order):
 * 1. scope === 'doc-only'         → only spec-compliance (all others: doc-only-scope)
 * 2. target in META_LIKE_TARGETS  → spec-compliance + security-scan (lint/tests/typecheck: meta-target)
 * 3. Everything else              → all 5 dimensions
 *
 * The `meta` target value used in the spec prose maps to 'infrastructure' | 'database' | 'shared'
 * in our actual SpecTarget type. Callers that need the `meta` semantic should store 'infrastructure'.
 */
export function resolveApplicableDimensions(spec) {
    const { target } = spec;
    // scope is SpecScope at the type level, but frontmatter may carry 'doc-only' at runtime
    const scope = spec.scope;
    // Rule 1: doc-only scope — only spec-compliance applies
    if (scope === 'doc-only') {
        const skipped = ALL_DIMENSIONS.filter((d) => d !== 'spec-compliance').map((d) => ({ dimension: d, reason: 'doc-only-scope' }));
        return { applicable: ['spec-compliance'], skipped };
    }
    // Rule 2: meta-like targets skip lint + tests + typecheck
    if (META_LIKE_TARGETS.has(target)) {
        const metaApplicable = ['spec-compliance', 'security-scan'];
        const skipped = ['tests', 'lint', 'typecheck'].map((d) => ({ dimension: d, reason: 'meta-target' }));
        return { applicable: metaApplicable, skipped };
    }
    // Rule 3: all other targets (backend, frontend, fullstack, ios, android) run all 5
    return { applicable: [...ALL_DIMENSIONS], skipped: [] };
}
/**
 * Normalise a dimension score sum over the applicable set.
 * Returns null when the applicable set is empty (no division by zero).
 */
export function normaliseScore(dimensionScores, applicable) {
    if (applicable.length === 0) {
        return null;
    }
    const total = applicable.reduce((sum, d) => sum + (dimensionScores[d] ?? 0), 0);
    return Math.round(total / applicable.length);
}
//# sourceMappingURL=scope-resolver.js.map