diff --git a/packages/c0py-core/src/verification/fidelity.ts b/packages/c0py-core/src/verification/fidelity.ts new file mode 100644 index 0000000..85c8e79 --- /dev/null +++ b/packages/c0py-core/src/verification/fidelity.ts @@ -0,0 +1,58 @@ +import type { FidelityVector } from "@siax/c0py-types"; + +export interface FidelityPolicy { + minimum: Partial>; + requireZeroRuntimeErrors?: boolean; + requireProductionBuild?: boolean; +} + +export interface FidelityGateResult { + passed: boolean; + failures: string[]; +} + +export const defaultClonePolicy: FidelityPolicy = { + minimum: { + routeCoverage: 1, + interactionCoverage: 1, + workflowCoverage: 1, + networkContractParity: 1, + responsiveCoverage: 1, + assets: 1, + accessibilityPass: true, + }, + requireZeroRuntimeErrors: true, + requireProductionBuild: true, +}; + +export function evaluateFidelity( + vector: FidelityVector, + policy: FidelityPolicy = defaultClonePolicy, +): FidelityGateResult { + const failures: string[] = []; + + for (const [dimension, requirement] of Object.entries(policy.minimum) as Array< + [keyof FidelityVector, number | boolean] + >) { + const actual = vector[dimension]; + + if (typeof requirement === "boolean") { + if (actual !== requirement) failures.push(`${dimension}: expected ${requirement}, got ${String(actual)}`); + continue; + } + + if (typeof actual !== "number" || actual < requirement) { + failures.push(`${dimension}: expected >= ${requirement}, got ${String(actual)}`); + } + } + + if (policy.requireZeroRuntimeErrors && vector.runtimeErrorCount !== 0) { + failures.push(`runtimeErrorCount: expected 0, got ${String(vector.runtimeErrorCount)}`); + } + + if (policy.requireProductionBuild && vector.productionBuildPass !== true) { + failures.push(`productionBuildPass: expected true, got ${String(vector.productionBuildPass)}`); + } + + return { passed: failures.length === 0, failures }; +}