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 { 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 { 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 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)); };