# core/resolvers/plan.resolver.ts

> 121 lines of code and 22 definitions.

Tree: GovLab Quality
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/quality#file-quality-core-resolvers-plan-resolver-ts
Source text: https://banes-lab.com/source/quality/core/resolvers/plan.resolver.ts.txt

Listed in [core/resolvers](https://banes-lab.com/api/source/quality/core/resolvers.md), after [core/resolvers/package.resolver.ts](https://banes-lab.com/source/quality/core/resolvers/package.resolver.ts.md) and before [core/resolvers/rule.resolver.ts](https://banes-lab.com/source/quality/core/resolvers/rule.resolver.ts.md).

## Definitions

- `bindingsForSetting` (lexical_declaration, line 39)
- `channelOf` (lexical_declaration, line 51)
- `bindings` (lexical_declaration, line 55)
- `collectConflicts` (lexical_declaration, line 83)
- `Binding` (interface_declaration, line 19)
- `BindCtx` (interface_declaration, line 26)
- `BindResult` (interface_declaration, line 34)
- `rows` (lexical_declaration, line 44)
- `langRows` (lexical_declaration, line 46)
- `out` (lexical_declaration, line 56)
- `setting` (lexical_declaration, line 59)
- `CollectCtx` (interface_declaration, line 75)
- `valueConflicts` (lexical_declaration, line 84)
- `resolveConfig` (lexical_declaration, line 111, exported)
- `perTool` (lexical_declaration, line 115, exported)
- `settingById` (lexical_declaration, line 116, exported)
- `shared` (lexical_declaration, line 119, exported)
- `ownership` (lexical_declaration, line 120, exported)
- `valueBinds` (lexical_declaration, line 121, exported)
- `enabledBinds` (lexical_declaration, line 122, exported)
- `conflicts` (lexical_declaration, line 127, exported)
- `blocking` (lexical_declaration, line 128, exported)

## Contained in

- [core/resolvers](https://banes-lab.com/anatomy/quality/folder-quality-core-resolvers.md)

## Uses

- [configuration/strings/quality.strings.ts](https://banes-lab.com/source/quality/configuration/strings/quality.strings.ts.md)
- [core/resolvers/surface.resolver.ts](https://banes-lab.com/source/quality/core/resolvers/surface.resolver.ts.md)

## Linked from

- [configuration/strings](https://banes-lab.com/anatomy/quality/folder-quality-configuration-strings.md)
- [core/resolvers](https://banes-lab.com/anatomy/quality/folder-quality-core-resolvers.md)

## Source

```typescript
import type {
    CanonicalConfig,
    CanonicalData,
    CanonicalSettingRecord,
    MappingRow,
    OwnershipSurface,
} from "#types/canon.types";
import type { Conflict, ConflictReport, PerTool, ResolvedPlan } from "#types/plan.types";
import {
    applyRuleIntent,
    applyValueSetting,
    detectKnownBadPairs,
    indexOwnership,
    indexRows,
    matchesLang,
} from "#core/resolvers/surface.resolver";
import { channelMismatch, unknownSetting } from "#configuration/strings/quality.strings";

interface Binding {
    setting: CanonicalSettingRecord;
    value: unknown;
    lang: string;
    langRows: MappingRow[];
}

interface BindCtx {
    entries: [string, unknown][];
    expectKind: "rule-intent" | "value";
    languages: string[];
    rowsById: Map<string, MappingRow[]>;
    settingById: Map<string, CanonicalSettingRecord>;
}

interface BindResult {
    bindings: Binding[];
    conflicts: Conflict[];
}

const bindingsForSetting = function bindingsForSetting(
    setting: CanonicalSettingRecord,
    value: unknown,
    ctx: BindCtx,
): Binding[] {
    const rows = ctx.rowsById.get(setting.id) ?? [];
    return ctx.languages.flatMap((lang) => {
        const langRows = rows.filter((row) => matchesLang(row, lang));
        return langRows.length > 0 ? [{ lang, langRows, setting, value }] : [];
    });
};

const channelOf = function channelOf(kind: BindCtx["expectKind"]): string {
    return kind === "value" ? "values" : "enabled";
};

const bindings = function bindings(ctx: BindCtx): BindResult {
    const out: Binding[] = [];
    const conflicts: Conflict[] = [];
    for (const [canonicalId, value] of ctx.entries) {
        const setting = ctx.settingById.get(canonicalId);
        if (!setting) {
            conflicts.push({ canonicalId, detail: unknownSetting(canonicalId), kind: "unknown-setting" });
        } else if (setting.kind === ctx.expectKind) {
            out.push(...bindingsForSetting(setting, value, ctx));
        } else {
            conflicts.push({
                canonicalId,
                detail: channelMismatch(canonicalId, setting.kind, channelOf(ctx.expectKind)),
                kind: "channel-mismatch",
            });
        }
    }
    return { bindings: out, conflicts };
};

interface CollectCtx {
    data: CanonicalData;
    enabledBinds: BindResult;
    ownership: Map<string, OwnershipSurface>;
    perTool: PerTool;
    valueBinds: BindResult;
}

const collectConflicts = function collectConflicts(ctx: CollectCtx): Conflict[] {
    const valueConflicts = ctx.valueBinds.bindings.flatMap((bind) =>
        applyValueSetting({
            lang: bind.lang,
            langRows: bind.langRows,
            ownership: ctx.ownership,
            perTool: ctx.perTool,
            setting: bind.setting,
            value: bind.value,
        }),
    );
    for (const bind of ctx.enabledBinds.bindings) {
        applyRuleIntent({
            lang: bind.lang,
            langRows: bind.langRows,
            ownership: ctx.ownership,
            perTool: ctx.perTool,
            setting: bind.setting,
        });
    }
    return [
        ...ctx.valueBinds.conflicts,
        ...ctx.enabledBinds.conflicts,
        ...valueConflicts,
        ...detectKnownBadPairs(ctx.data, ctx.perTool),
    ];
};

export const resolveConfig = function resolveConfig(
    config: CanonicalConfig,
    data: CanonicalData,
): ConflictReport | ResolvedPlan {
    const perTool: PerTool = {};
    const settingById = new Map(
        data.settings.map((setting): [string, CanonicalSettingRecord] => [setting.id, setting]),
    );
    const shared = { languages: config.languages, rowsById: indexRows(data.rows), settingById };
    const ownership = indexOwnership(data.ownership);
    const valueBinds = bindings({ ...shared, entries: Object.entries(config.values ?? {}), expectKind: "value" });
    const enabledBinds = bindings({
        ...shared,
        entries: Object.entries(config.enabled ?? {}).filter(([, on]) => on),
        expectKind: "rule-intent",
    });
    const conflicts = collectConflicts({ data, enabledBinds, ownership, perTool, valueBinds });
    const blocking = conflicts.filter((conflict) => conflict.kind !== "unsatisfiable-on-fixed");
    return blocking.length > 0 ? { conflicts: blocking } : { perToolConfig: perTool };
};
```
