packages feed

canontra-0.1.0.0: src/Canontra/Verification/Determinism.hs

{- |
Module      : Canontra.Verification.Determinism
Description : Multi-run determinism verification engine for v0.0.3-alpha.

Determinism verification enforces the core alpha contract:
repeated executions on identical input must yield byte-for-byte identical
fingerprints across all 8 tiers, eliminating hidden state or non-deterministic ordering.
-}
module Canontra.Verification.Determinism
  ( verifyDeterminism
  , verifyDeterminismBytes
  , formatVerificationResult
  ) where

import qualified Data.ByteString as BS
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE

import Canontra.Fingerprint.Bundle (computeBundle)
import Canontra.Types

verifyDeterminism :: Int -> FilePath -> Text -> Either ParseError VerificationResult
verifyDeterminism runs filePath src =
  verifyDeterminismBytes runs filePath (TE.encodeUtf8 src) src

verifyDeterminismBytes :: Int -> FilePath -> BS.ByteString -> Text -> Either ParseError VerificationResult
verifyDeterminismBytes runs filePath rawBytes src = do
  firstBundle <- computeBundle filePath rawBytes src
  let runCount = max 2 runs
      results = map (\_ -> computeBundle filePath rawBytes src) [2 .. runCount]
  case sequence results of
    Left err -> Left err
    Right bundles ->
      let allBundles = firstBundle : bundles
          f1Matches  = all (\b -> f1Structural b == f1Structural firstBundle) allBundles
          f2Matches  = all (\b -> f2Declaration b == f2Declaration firstBundle) allBundles
          f3Matches  = all (\b -> f3Dependency b == f3Dependency firstBundle) allBundles
          fcgMatches = all (\b -> fCGCallGraph b == fCGCallGraph firstBundle) allBundles
          fcfMatches = all (\b -> fCFControlFlow b == fCFControlFlow firstBundle) allBundles
          fdfMatches = all (\b -> fDFDataFlow b == fDFDataFlow firstBundle) allBundles
          f4Matches  = all (\b -> f4Composite b == f4Composite firstBundle) allBundles
          isDet = f1Matches && f2Matches && f3Matches && fcgMatches && fcfMatches && fdfMatches && f4Matches
      in Right $ VerificationResult
          { vrRuns            = runCount
          , vrStructuralPass  = f1Matches
          , vrDeclarationPass = f2Matches
          , vrDependencyPass  = f3Matches
          , vrCallGraphPass   = fcgMatches
          , vrControlFlowPass = fcfMatches
          , vrDataFlowPass    = fdfMatches
          , vrCompositePass   = f4Matches
          , vrDeterministic   = isDet
          }

formatVerificationResult :: VerificationResult -> Text
formatVerificationResult vr =
  T.unlines
    [ "================================================================================"
    , "  CANONTRA REPEAT-EXECUTION DETERMINISM VERIFICATION"
    , "================================================================================"
    , "  Verification Runs:     " <> T.pack (show (vrRuns vr)) <> " iterations"
    , "  Final Verdict:         " <> (if vrDeterministic vr then "DETERMINISTIC INVARIANCE VERIFIED" else "NON-DETERMINISTIC FAILURE DETECTED")
    , "--------------------------------------------------------------------------------"
    , "  Tier Invariant Check                              Status"
    , "--------------------------------------------------------------------------------"
    , "  F1  (Structural AST Normalization):               " <> passFail (vrStructuralPass vr)
    , "  F2  (Declaration Hierarchy Matrix):               " <> passFail (vrDeclarationPass vr)
    , "  F3  (Dependency & Module Graph):                  " <> passFail (vrDependencyPass vr)
    , "  FCG (Intra-Module Call Graph Topology):           " <> passFail (vrCallGraphPass vr)
    , "  FCF (Control-Flow Graph Invariance):              " <> passFail (vrControlFlowPass vr)
    , "  FDF (Data-Flow SSA Graph Invariance):             " <> passFail (vrDataFlowPass vr)
    , "  F4  (Composite Deterministic Identity):           " <> passFail (vrCompositePass vr)
    , "================================================================================"
    ]
  where
    passFail True  = "[PASS] 100% Bit-Identical"
    passFail False = "[FAIL] Divergence Detected"