import type { Faces, IncompleteSeed, LessonSeed, SeedReport } from "#types/lesson.types"; import { SEED_LEVELS, VERIFY_STAGE } from "#configuration/constants/seed.constants"; import type { Contract } from "@govlab/context/algo"; const SOURCE = "algo"; 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, forces: readonly string[]): string[] { const names = new Set(); for (const force of forces) { for (const principle of faces.arch.query({ scope: force })) { names.add(principle.name); } } return [...names].sort((a, b) => a.localeCompare(b)); }; const seedOf = function seedOf(faces: Faces, meta: Contract, kernel: Contract | null): LessonSeed { const before = kernel?.exemplar?.before ?? null; return { application: meta.flow, boundary: null, cause: causesOf(faces, meta.force), decision: meta.intent, domain: meta.domain, failureMode: before, id: meta.id, level: SEED_LEVELS[SOURCE], principle: meta.invariant, problem: before, source: SOURCE, validation: validationOf(faces, kernel), }; }; export const missingFieldsOf = function missingFieldsOf(seed: LessonSeed): string[] { const missing: string[] = []; if (seed.problem === null) { missing.push("problem"); } if (seed.cause.length === 0) { missing.push("cause"); } if (seed.validation === null) { missing.push("validation"); } if (seed.principle.length === 0) { missing.push("principle"); } return missing; }; 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)); };