core/converters/lesson.converter.ts

core/converters/lesson.converter.ts is a file in Bane's Lab Content. 99 lines of code and 27 definitions.

import { ARCH_FACE, FACE_SEPARATOR, LEX_FACE } from "@govlab/constants";
import type { Contract, Principle } from "@govlab/context";
import type { Faces, IncompleteSeed, LessonSeed, SeedField, SeedReport } from "#types/lesson.types";
import { SEED_FIELDS, SEED_LEVELS, VERIFY_STAGE } from "#configuration/constants/seed.constants";

const SOURCE = "algorithms";
const LABEL_JOINER = ", ";

type SourcedField = "failureMode" | "problem" | "validation";

const kernelOf = function kernelOf(contracts: readonly Contract[], domain: string): Contract | null {
    return contracts.find((contract) => contract.domain === domain && contract.derivationMap !== undefined) ?? null;
};

const validationOf = function validationOf(faces: Faces, kernel: Contract | null): string | null {
    const entry = kernel?.derivationMap?.find((mapped) => mapped.stage === VERIFY_STAGE);
    if (entry === undefined) {
        return null;
    }
    const record = faces.algo.get(entry.record);
    return record === null || record.invariant.length === 0 ? null : record.invariant;
};

const causesOf = function causesOf(faces: Faces, meta: Contract, kernel: Contract | null): string[] {
    const refs = [meta, ...(kernel ? [kernel] : []), ...meta.composes.flatMap((id) => faces.algo.get(id) ?? [])]
        .map((contract) => contract.principleRef)
        .filter((ref): ref is string => typeof ref === "string");
    const names = new Set(refs.flatMap((ref) => faces.arch.get(ref)?.name ?? []));
    return [...names].sort((a, b) => a.localeCompare(b));
};

const governingOf = function governingOf(faces: Faces, meta: Contract): Principle | null {
    return typeof meta.principleRef === "string" ? faces.arch.get(meta.principleRef) : null;
};

const textOrNull = function textOrNull(value: string | undefined): string | null {
    return value === undefined || value.trim().length === 0 ? null : value;
};

const ARCH_PREFIX = ARCH_FACE + FACE_SEPARATOR;
const LEX_PREFIX = LEX_FACE + FACE_SEPARATOR;

const violationTextOf = function violationTextOf(faces: Faces, ref: string): string | undefined {
    if (ref.startsWith(ARCH_PREFIX)) {
        return faces.arch.get(ref.slice(ARCH_PREFIX.length))?.formed_by;
    }
    return ref.startsWith(LEX_PREFIX) ? faces.lex.get(ref.slice(LEX_PREFIX.length))?.definition : undefined;
};

const formationOf = function formationOf(faces: Faces, governing: Principle | null): string | undefined {
    if (governing === null || governing.formed_by !== undefined) {
        return governing?.formed_by;
    }
    return (governing.violated_by ?? []).map((ref) => violationTextOf(faces, ref)).find((text) => text !== undefined);
};

const kernelSeedOf = function kernelSeedOf(faces: Faces, kernel: Contract): Pick<LessonSeed, SourcedField> {
    const before = kernel.exemplar?.before ?? null;
    return { failureMode: before, problem: before, validation: validationOf(faces, kernel) };
};

const clusterSeedOf = function clusterSeedOf(
    faces: Faces,
    governing: Principle | null,
): Pick<LessonSeed, SourcedField> {
    return {
        failureMode: textOrNull(governing?.exemplar?.before),
        problem: textOrNull(formationOf(faces, governing)),
        validation: textOrNull(governing?.detected_by.join(LABEL_JOINER)),
    };
};

const seedOf = function seedOf(faces: Faces, meta: Contract, kernel: Contract | null): LessonSeed {
    return {
        application: meta.flow,
        boundary: null,
        cause: causesOf(faces, meta, kernel),
        decision: meta.intent,
        domain: meta.domain,
        id: meta.id,
        level: SEED_LEVELS[SOURCE],
        principle: meta.invariant,
        source: SOURCE,
        ...(kernel ? kernelSeedOf(faces, kernel) : clusterSeedOf(faces, governingOf(faces, meta))),
    };
};

const FIELD_ABSENT: Readonly<Record<SeedField, (seed: LessonSeed) => boolean>> = {
    cause: (seed) => seed.cause.length === 0,
    principle: (seed) => seed.principle.length === 0,
    problem: (seed) => seed.problem === null,
    validation: (seed) => seed.validation === null,
};

export const missingFieldsOf = function missingFieldsOf(seed: LessonSeed): string[] {
    return SEED_FIELDS[seed.source].filter((field) => FIELD_ABSENT[field](seed));
};

export const reportOf = function reportOf(seeds: readonly LessonSeed[]): SeedReport {
    const incomplete: IncompleteSeed[] = [];
    for (const seed of seeds) {
        const missing = missingFieldsOf(seed);
        if (missing.length > 0) {
            incomplete.push({ id: seed.id, missing });
        }
    }
    return { incomplete, seeds };
};

export const algoSeeds = function algoSeeds(faces: Faces): LessonSeed[] {
    const contracts = faces.algo.all();
    return faces.algo
        .query({ meta: true })
        .map((meta) => seedOf(faces, meta, kernelOf(contracts, meta.domain)))
        .sort((a, b) => a.id.localeCompare(b.id));
};