diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,11 +6,23 @@
 and this project adheres to the
 [Haskell Package Versioning Policy](https://pvp.haskell.org/).
 
+## v3.1.0 - 2024-12-28
+
+### Breaking changes
+
+- Use `new.yaml` in the CLI by default ([#658](https://github.com/objectionary/eo-phi-normalizer/pull/658))
+
+### Changes and fixes
+
+- Simplify pipeline config format ([#648](https://github.com/objectionary/eo-phi-normalizer/pull/648))
+- Use dependencies for EO 0.50.0 ([#653](https://github.com/objectionary/eo-phi-normalizer/pull/653))
+- Add tests from hone-maven-plugin ([#655](https://github.com/objectionary/eo-phi-normalizer/pull/655))
+
 ## v3.0.0 - 2024-12-28
 
 ### Breaking changes
 
-- Switch to built-in rules until `new.yaml` rules work ([#619](https://github.com/objectionary/eo-phi-normalizer/pull/619))
+- Switch to built-in rules in the pipeline until `new.yaml` rules work ([#619](https://github.com/objectionary/eo-phi-normalizer/pull/619))
 - Update EO to 0.50.0, use `yegor.yaml` by default ([#617](https://github.com/objectionary/eo-phi-normalizer/pull/617), [#641](https://github.com/objectionary/eo-phi-normalizer/pull/641))
 
 ### Changes and fixes
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -65,7 +65,7 @@
 import Data.Text.Lazy as TL (unpack)
 import Data.Text.Lazy.Manipulate (toOrdinal)
 import Data.Version (showVersion)
-import Data.Yaml (decodeFileThrow, decodeThrow)
+import Data.Yaml (decodeThrow, encodeFile)
 import GHC.Generics (Generic)
 import Language.EO.Locale (withCorrectLocale)
 import Language.EO.Phi (Binding (..), Bytes (Bytes), Object (..), Program (Program), parseProgram, printTree)
@@ -276,7 +276,7 @@
   }
 
 rulesFile :: String
-rulesFile = "yegor.yaml"
+rulesFile = "new.yaml"
 
 commandParser :: CommandParser
 commandParser =
@@ -607,7 +607,7 @@
           -- Temporary hack while rules are not stabilized.
           -- Nothing -> return (True, "Yegor's rules (builtin)", [fastYegorInsideOutAsRule])
           Nothing -> do
-            ruleSet :: RuleSet <- decodeThrow $(embedFileRelative "test/eo/phi/rules/yegor.yaml")
+            ruleSet :: RuleSet <- decodeThrow $(embedFileRelative "test/eo/phi/rules/new.yaml")
             return (False, ruleSet.title, convertRuleNamed <$> ruleSet.rules)
       unless (single || json || latex) $ logStrLn ruleSetTitle
       bindingsWithDeps <- case deepMergePrograms (program' : deps) of
@@ -766,7 +766,8 @@
                in logStrLn (printAsProgramOrAsObject obj'')
             Right (Bytes bytes) -> logStrLn bytes
     CLI'Pipeline' (CLI'Pipeline'Report' CLI'Pipeline'Report{..}) -> do
-      pipelineConfig <- decodeFileThrow @_ @PipelineConfig configFile
+      pipelineConfig <- readPipelineConfig configFile
+      encodeFile "abra.yaml" pipelineConfig
       let testSets = filter (fromMaybe True . (.enable)) pipelineConfig.testSets
       programReports <- forM (zip [1 ..] testSets) $ \(index :: Int, (.phi) -> testSet) -> do
         let progress = [fmt|({index}/{length testSets})|] :: String
@@ -796,10 +797,10 @@
           createDirectoryIfMissing True (takeDirectory path)
           writeFile path reportString
     CLI'Pipeline' (CLI'Pipeline'PrepareTests' CLI'Pipeline'PrepareTests{..}) -> do
-      config <- decodeFileThrow @_ @PipelineConfig configFile
+      config <- readPipelineConfig configFile
       PrepareTests.prepareTests config
     CLI'Pipeline' (CLI'Pipeline'PrintDataizeConfigs' CLI'Pipeline'PrintDataizeConfigs{..}) -> do
-      config <- decodeFileThrow @_ @PipelineConfig configFile
+      config <- readPipelineConfig configFile
       PrintConfigs.printDataizeConfigs config phiPrefixesToStrip singleLine
     CLI'Test' (CLI'Test{..}) ->
       evalSpec defaultConfig (spec rulePaths)
diff --git a/eo-phi-normalizer.cabal b/eo-phi-normalizer.cabal
--- a/eo-phi-normalizer.cabal
+++ b/eo-phi-normalizer.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           eo-phi-normalizer
-version:        3.0.0
+version:        3.1.0
 synopsis:       Command line normalizer of 𝜑-calculus expressions.
 description:    Please see the README on GitHub at <https://github.com/objectionary/eo-phi-normalizer#readme>
 homepage:       https://github.com/objectionary/eo-phi-normalizer#readme
@@ -390,6 +390,11 @@
     data/0.50.0/org/eolang/tuple.phi
     data/0.50.0/org/eolang/txt/sprintf.phi
     data/0.50.0/org/eolang/while.phi
+    test/eo/phi/confluence.yaml
+    test/eo/phi/dataization.yaml
+    test/eo/phi/from-eo/as-phi.yaml
+    test/eo/phi/metrics.yaml
+    test/eo/phi/rewriting.yaml
     test/eo/phi/rules/new.yaml
     test/eo/phi/rules/streams.yaml
     test/eo/phi/rules/yegor.yaml
@@ -430,7 +435,6 @@
       Language.EO.Phi.Report.Html
       Language.EO.Phi.Rules.Common
       Language.EO.Phi.Rules.Fast
-      Language.EO.Phi.Rules.PhiPaper
       Language.EO.Phi.Rules.RunYegor
       Language.EO.Phi.Rules.Yaml
       Language.EO.Phi.Syntax
@@ -561,7 +565,6 @@
       Language.EO.Phi.Report.Html
       Language.EO.Phi.Rules.Common
       Language.EO.Phi.Rules.Fast
-      Language.EO.Phi.Rules.PhiPaper
       Language.EO.Phi.Rules.RunYegor
       Language.EO.Phi.Rules.Yaml
       Language.EO.Phi.Syntax
@@ -625,6 +628,7 @@
   main-is: Main.hs
   other-modules:
       Language.EO.Phi.DataizeSpec
+      Language.EO.Phi.RewriteSpec
       Language.EO.PhiSpec
       Language.EO.Rules.PhiPaperSpec
       Language.EO.YamlSpec
diff --git a/src/Language/EO/Phi.hs b/src/Language/EO/Phi.hs
--- a/src/Language/EO/Phi.hs
+++ b/src/Language/EO/Phi.hs
@@ -22,21 +22,18 @@
 -- SOFTWARE.
 {- FOURMOLU_ENABLE -}
 module Language.EO.Phi (
-  defaultMain,
   normalize,
   parseProgram,
   unsafeParseObject,
   unsafeParseProgram,
+  unsafeParseProgramFromFile,
   module Language.EO.Phi.Syntax,
 ) where
 
-import System.Exit (exitFailure)
-
-import Language.EO.Phi.Syntax.Abs qualified as Phi
-import Language.EO.Phi.Syntax.Par qualified as Phi
-
 import Language.EO.Phi.Normalize
 import Language.EO.Phi.Syntax
+import Language.EO.Phi.Syntax.Abs qualified as Phi
+import Language.EO.Phi.Syntax.Par qualified as Phi
 
 -- | Parse a 'Program' or return a parsing error.
 parseProgram :: String -> Either String Phi.Program
@@ -59,16 +56,9 @@
 unsafeParseObject :: String -> Phi.Object
 unsafeParseObject = either error id . parseObject
 
--- | Default entry point.
--- Parses a 𝜑-program from standard input, normalizes,
--- then pretty-prints the result to standard output.
-defaultMain :: IO ()
-defaultMain = do
-  input <- getContents -- read entire standard input
-  let tokens = Phi.myLexer input
-  case Phi.pProgram tokens of
-    Left parseError -> do
-      putStrLn parseError
-      exitFailure
-    Right program -> do
-      putStrLn (printTree (normalize program))
+unsafeParseProgramFromFile :: FilePath -> IO Phi.Program
+unsafeParseProgramFromFile inputFile = do
+  src <- readFile inputFile
+  case parseProgram src of
+    Left err -> error ("Error parsing program from '" ++ inputFile ++ "':\n" ++ err)
+    Right program -> pure program
diff --git a/src/Language/EO/Phi/Pipeline/Config.hs b/src/Language/EO/Phi/Pipeline/Config.hs
--- a/src/Language/EO/Phi/Pipeline/Config.hs
+++ b/src/Language/EO/Phi/Pipeline/Config.hs
@@ -27,17 +27,28 @@
 {-# LANGUAGE DuplicateRecordFields #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE InstanceSigs #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedRecordDot #-}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeApplications #-}
 {-# OPTIONS_GHC -Wno-partial-fields #-}
 
 module Language.EO.Phi.Pipeline.Config where
 
+import Control.Monad.IO.Class (MonadIO)
 import Data.Aeson (ToJSON)
 import Data.Aeson.Types (FromJSON)
+import Data.Functor ((<&>))
+import Data.List (intercalate)
+import Data.Yaml (decodeFileThrow)
 import GHC.Generics (Generic)
 import Language.EO.Phi.Metrics.Data
 import Language.EO.Phi.TH (deriveJSON)
+import PyF (fmt)
 import Text.Printf (printf)
 
 data TestSetPhi = TestSetPhi
@@ -127,16 +138,65 @@
 
 $(deriveJSON ''AtomsSet)
 
-data TestSet = TestSet
-  { eo :: TestSetEO
-  , phi :: TestSetPhi
-  , atoms :: Maybe AtomsSet
+data PathPrefixEO = PathPrefixEO
+  { original :: FilePath
+  , yaml :: FilePath
+  , filtered :: FilePath
+  }
+  deriving stock (Show, Generic)
+
+$(deriveJSON ''PathPrefixEO)
+
+data PathPrefixPhi = PathPrefixPhi
+  { initial :: FilePath
+  , normalized :: FilePath
+  }
+  deriving stock (Show, Generic)
+
+$(deriveJSON ''PathPrefixPhi)
+
+data PathPrefix = PathPrefix
+  { eo :: PathPrefixEO
+  , phi :: PathPrefixPhi
+  }
+  deriving stock (Show, Generic)
+
+$(deriveJSON ''PathPrefix)
+
+data Common = Common
+  { pathPrefix :: PathPrefix
+  , bindingsPath :: Maybe String
+  }
+  deriving stock (Show, Generic)
+
+$(deriveJSON ''Common)
+
+data Individual = Individual
+  { name :: String
   , enable :: Maybe Bool
-  -- ^
-  -- Whether to enable this test set.
+  , include :: Maybe [String]
+  , exclude :: Maybe [String]
+  , atoms :: Maybe AtomsSet
   }
   deriving stock (Show, Generic)
 
+$(deriveJSON ''Individual)
+
+data TestSet
+  = TestSetExtended
+      { eo :: TestSetEO
+      , phi :: TestSetPhi
+      , atoms :: Maybe AtomsSet
+      , enable :: Maybe Bool
+      -- ^
+      -- Whether to enable this test set.
+      }
+  | TestSetCompact
+      { common :: Common
+      , individual :: [Individual]
+      }
+  deriving stock (Show, Generic)
+
 $(deriveJSON ''TestSet)
 
 data PipelineConfig = PipelineConfig
@@ -152,3 +212,46 @@
   | -- | GitHub Flavored Markdown
     ReportFormat'Markdown
   deriving stock (Eq)
+
+split :: forall a. (a -> Bool) -> [a] -> [[a]]
+split cond xs = go xs [] []
+ where
+  go [] _ res = res
+  go (y : ys) curSpan res
+    | cond y = go ys [] (res <> [curSpan])
+    | otherwise = go ys (curSpan <> [y]) res
+
+-- >>> split @Int (== 3) [1,2,3,3,4,3]
+
+toExtended :: PipelineConfig -> PipelineConfig
+toExtended c@(PipelineConfig{testSets}) = c{testSets = concatMap go testSets}
+ where
+  go = \case
+    e@TestSetExtended{} -> [e]
+    TestSetCompact{..} -> go1 common <$> individual
+
+  go1 (Common{..}) (Individual{..}) = TestSetExtended{..}
+   where
+    mkPath :: FilePath -> String -> String
+    mkPath prefix extension = [fmt|{prefix}/{name}.{extension}|]
+    eo =
+      TestSetEO
+        { original = mkPath pathPrefix.eo.original "eo"
+        , yaml = mkPath pathPrefix.eo.yaml "yaml"
+        , filtered = mkPath pathPrefix.eo.filtered "eo"
+        , include
+        , exclude
+        }
+    phi =
+      TestSetPhi
+        { initial = mkPath pathPrefix.phi.initial "phi"
+        , normalized = mkPath pathPrefix.phi.normalized "phi"
+        , bindingsPathInitial = bindingsPath <&> mkBindingsPathSuffix
+        , bindingsPathNormalized = bindingsPath <&> mkBindingsPathSuffix
+        }
+     where
+      name' = split (== '/') name
+      mkBindingsPathSuffix x = x <> intercalate "." (if name' /= [] then init name' else [])
+
+readPipelineConfig :: (MonadIO m) => FilePath -> m PipelineConfig
+readPipelineConfig path = toExtended <$> decodeFileThrow @_ @PipelineConfig path
diff --git a/src/Language/EO/Phi/Rules/PhiPaper.hs b/src/Language/EO/Phi/Rules/PhiPaper.hs
deleted file mode 100644
--- a/src/Language/EO/Phi/Rules/PhiPaper.hs
+++ /dev/null
@@ -1,42 +0,0 @@
-{- FOURMOLU_DISABLE -}
--- The MIT License (MIT)
-
--- Copyright (c) 2016-2024 Objectionary.com
-
--- Permission is hereby granted, free of charge, to any person obtaining a copy
--- of this software and associated documentation files (the "Software"), to deal
--- in the Software without restriction, including without limitation the rights
--- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
--- copies of the Software, and to permit persons to whom the Software is
--- furnished to do so, subject to the following conditions:
-
--- The above copyright notice and this permission notice shall be included
--- in all copies or substantial portions of the Software.
-
--- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
--- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
--- FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
--- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
--- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
--- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
--- SOFTWARE.
-{- FOURMOLU_ENABLE -}
-module Language.EO.Phi.Rules.PhiPaper where
-
-import Control.Monad (guard)
-import Language.EO.Phi
-import Language.EO.Phi.Rules.Common
-
--- * Yegor's Rules
-
--- | Rule 6.
-rule6 :: Rule
-rule6 ctx (ObjectDispatch (Formation bindings) a)
-  | Just obj <- lookupBinding a bindings = do
-      guard (isNF ctx obj)
-      return (Application obj [AlphaBinding Rho (Formation bindings')])
- where
-  bindings' = filter (not . isDispatched) bindings
-  isDispatched (AlphaBinding a' _) = a == a'
-  isDispatched _ = False
-rule6 _ _ = []
diff --git a/src/Language/EO/Phi/TH.hs b/src/Language/EO/Phi/TH.hs
--- a/src/Language/EO/Phi/TH.hs
+++ b/src/Language/EO/Phi/TH.hs
@@ -23,13 +23,21 @@
 {- FOURMOLU_ENABLE -}
 module Language.EO.Phi.TH where
 
-import Data.Aeson (Options (..), camelTo2)
-import Data.Aeson.TH as TH (deriveJSON)
+import Data.Aeson (Options (..), SumEncoding (..), camelTo2)
+import Data.Aeson.TH as TH (deriveFromJSON, deriveJSON)
 import Data.Aeson.Types (defaultOptions)
 import Language.Haskell.TH (Dec, Name, Q)
 
 defaultOptions' :: Options
-defaultOptions' = defaultOptions{fieldLabelModifier = camelTo2 '-', rejectUnknownFields = True}
+defaultOptions' =
+  defaultOptions
+    { fieldLabelModifier = camelTo2 '-'
+    , rejectUnknownFields = True
+    , sumEncoding = UntaggedValue
+    }
 
 deriveJSON :: Name -> Q [Dec]
 deriveJSON = TH.deriveJSON defaultOptions'
+
+deriveFromJSON :: Name -> Q [Dec]
+deriveFromJSON = TH.deriveFromJSON defaultOptions'
diff --git a/test/Language/EO/Phi/DataizeSpec.hs b/test/Language/EO/Phi/DataizeSpec.hs
--- a/test/Language/EO/Phi/DataizeSpec.hs
+++ b/test/Language/EO/Phi/DataizeSpec.hs
@@ -38,7 +38,7 @@
 import Language.EO.Phi.Dependencies (deepMergePrograms)
 import Language.EO.Phi.Rules.Common (equalObject)
 import Language.EO.Phi.Rules.Yaml (convertRuleNamed, parseRuleSetFromFile, rules)
-import Test.EO.Phi (DataizationResult (Bytes, Object), DataizeTest (..), DataizeTestGroup (..), dataizationTests)
+import Test.EO.Phi (DataizationResult (Bytes, Object), DataizeTest (..), DataizeTestGroup (..), dataizationTests, progToObj)
 
 newtype ObjectOrBytes = ObjectOrBytes (Either Phi.Object Phi.Bytes)
 
@@ -53,13 +53,6 @@
     x == y
   _ == _ = False
 
-getProgram :: FilePath -> IO Phi.Program
-getProgram inputFile = do
-  src <- readFile inputFile
-  case Phi.parseProgram src of
-    Left err -> error ("Error parsing program from '" ++ inputFile ++ "': " ++ err)
-    Right program -> pure program
-
 spec :: Spec
 spec = do
   DataizeTestGroup{..} <- runIO (dataizationTests "test/eo/phi/dataization.yaml")
@@ -75,7 +68,7 @@
         describe rulesTitle do
           forM_ tests $
             \test -> do
-              deps <- runIO $ mapM getProgram test.dependencies
+              deps <- runIO $ mapM Phi.unsafeParseProgramFromFile test.dependencies
               let mergedProgs = case deepMergePrograms (test.input : deps) of
                     Left err -> error ("Error merging programs: " ++ err)
                     Right prog -> prog
@@ -87,6 +80,3 @@
               it test.name $ do
                 let dataizedResult = dataizeRecursively ctx inputObj
                 ObjectOrBytes dataizedResult `shouldBe` ObjectOrBytes expectedResult
-
-progToObj :: Phi.Program -> Phi.Object
-progToObj (Phi.Program bindings) = Phi.Formation bindings
diff --git a/test/Language/EO/Phi/RewriteSpec.hs b/test/Language/EO/Phi/RewriteSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Language/EO/Phi/RewriteSpec.hs
@@ -0,0 +1,81 @@
+{- FOURMOLU_DISABLE -}
+-- The MIT License (MIT)
+
+-- Copyright (c) 2016-2024 Objectionary.com
+
+-- Permission is hereby granted, free of charge, to any person obtaining a copy
+-- of this software and associated documentation files (the "Software"), to deal
+-- in the Software without restriction, including without limitation the rights
+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+-- copies of the Software, and to permit persons to whom the Software is
+-- furnished to do so, subject to the following conditions:
+
+-- The above copyright notice and this permission notice shall be included
+-- in all copies or substantial portions of the Software.
+
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-- SOFTWARE.
+{- FOURMOLU_ENABLE -}
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE OverloadedRecordDot #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeApplications #-}
+
+module Language.EO.Phi.RewriteSpec where
+
+import Control.Monad (forM_)
+import Data.Yaml qualified as Yaml
+import GHC.Generics (Generic)
+import Language.EO.Phi (Program (..))
+import Language.EO.Phi.Dataize.Context (defaultContext)
+import Language.EO.Phi.Rules.Common (applyRules)
+import Language.EO.Phi.Rules.Yaml (convertRuleNamed, parseRuleSetFromFile, rules)
+import Language.EO.Phi.Syntax (printTree)
+import Language.EO.Phi.TH
+import Test.EO.Phi (progToObj)
+import Test.Hspec
+
+data Test = Test
+  { name :: String
+  , input :: Program
+  , output :: Program
+  }
+  deriving stock (Generic, Show)
+
+$(deriveFromJSON ''Test)
+
+data RewriteTests = RewriteTests
+  { title :: String
+  , tests :: [Test]
+  }
+  deriving stock (Generic, Show)
+
+$(deriveFromJSON ''RewriteTests)
+
+spec :: Spec
+spec = do
+  rewriteTests <- runIO (Yaml.decodeFileThrow @_ @RewriteTests "test/eo/phi/rewriting.yaml")
+  describe rewriteTests.title do
+    forM_
+      [ ("New Yegor's rules", "test/eo/phi/rules/new.yaml")
+      ]
+      $ \(rulesTitle, rulesFile) -> do
+        ruleset <- runIO $ parseRuleSetFromFile rulesFile
+        let rules' = convertRuleNamed <$> ruleset.rules
+        describe rulesTitle do
+          forM_ rewriteTests.tests $
+            \test -> it test.name do
+              let
+                inputObj = progToObj test.input
+                expectedOutputObj = progToObj test.output
+                ctx = defaultContext rules' inputObj
+                outputObj = head $ applyRules ctx inputObj
+              printTree outputObj `shouldBe` printTree expectedOutputObj
diff --git a/test/Language/EO/PhiSpec.hs b/test/Language/EO/PhiSpec.hs
--- a/test/Language/EO/PhiSpec.hs
+++ b/test/Language/EO/PhiSpec.hs
@@ -25,10 +25,8 @@
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE OverloadedLists #-}
 {-# LANGUAGE OverloadedRecordDot #-}
-{-# LANGUAGE QuasiQuotes #-}
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE ViewPatterns #-}
 
 module Language.EO.PhiSpec where
 
@@ -37,15 +35,12 @@
 import Data.List (dropWhileEnd)
 import Data.String (IsString (..))
 import Data.Yaml (decodeFileThrow)
-import Language.EO.Phi
-import Language.EO.Phi.Dataize.Context (defaultContext)
+import Language.EO.Phi (Binding (..), Object, Program (..), normalize, printTree)
 import Language.EO.Phi.Metrics.Collect (getProgramMetrics)
 import Language.EO.Phi.Metrics.Data (BindingsByPathMetrics (..), ProgramMetrics (..))
-import Language.EO.Phi.Rules.Common (Rule, equalProgram)
-import Language.EO.Phi.Rules.PhiPaper (rule6)
-import PyF (fmt)
-import Test.EO.Phi
-import Test.Hspec
+import Language.EO.Phi.Rules.Common (equalProgram)
+import Test.EO.Phi (PhiTest (..), PhiTestGroup (..), allPhiTests)
+import Test.Hspec (Spec, describe, it, runIO, shouldBe, shouldSatisfy)
 import Test.Metrics.Phi (MetricsTest (..), MetricsTestSet (..))
 
 applyRule :: (Object -> [Object]) -> Program -> [Program]
@@ -57,15 +52,6 @@
 
 spec :: Spec
 spec = do
-  describe "Pre-defined rules" $
-    forM_ ([(6, rule6)] :: [(Int, Rule)]) $
-      \(idx, rule) -> do
-        PhiTestGroup{..} <- runIO (fileTests [fmt|test/eo/phi/rule-{idx}.yaml|])
-        describe title $
-          forM_ tests $
-            \PhiTest{..} ->
-              it name $
-                applyRule (rule (defaultContext [] (progToObj input))) input `shouldBe` [normalized]
   describe "Programs translated from EO" $ do
     phiTests <- runIO (allPhiTests "test/eo/phi/from-eo/")
     forM_ phiTests $ \PhiTestGroup{..} ->
@@ -86,6 +72,3 @@
 
 trim :: String -> String
 trim = dropWhileEnd isSpace
-
-progToObj :: Program -> Object
-progToObj (Program bindings) = Formation bindings
diff --git a/test/Test/EO/Phi.hs b/test/Test/EO/Phi.hs
--- a/test/Test/EO/Phi.hs
+++ b/test/Test/EO/Phi.hs
@@ -71,10 +71,12 @@
   , dependencies :: [FilePath]
   }
   deriving (Generic, FromJSON)
+
 data DataizationResult
   = Bytes {bytes :: Phi.Bytes}
   | Object {object :: Phi.Object}
   deriving (Generic, Show)
+
 instance FromJSON DataizationResult where
   parseJSON = genericParseJSON defaultOptions{sumEncoding = UntaggedValue}
 
@@ -101,3 +103,6 @@
   parseJSON = fmap unsafeParseObject . parseJSON
 
 deriving newtype instance FromJSON Phi.Bytes
+
+progToObj :: Phi.Program -> Phi.Object
+progToObj (Phi.Program bindings) = Phi.Formation bindings
diff --git a/test/eo/phi/confluence.yaml b/test/eo/phi/confluence.yaml
new file mode 100644
--- /dev/null
+++ b/test/eo/phi/confluence.yaml
@@ -0,0 +1,27 @@
+# The MIT License (MIT)
+
+# Copyright (c) 2016-2024 Objectionary.com
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+title: Manual (regression) tests for confluence
+tests:
+  - '⟦ ρ ↦ ⊥.a ⟧'
+  - '⟦ ρ ↦ ⊥ () ⟧'
+  - '⟦ v4 ↦ Φ (e6 ↦ ⟦ φ ↦ Φ ⟧.φ) ⟧'
diff --git a/test/eo/phi/dataization.yaml b/test/eo/phi/dataization.yaml
new file mode 100644
--- /dev/null
+++ b/test/eo/phi/dataization.yaml
@@ -0,0 +1,709 @@
+# The MIT License (MIT)
+
+# Copyright (c) 2016-2024 Objectionary.com
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+title: Dataization tests
+tests:
+  - name: "Celsius example"
+    dependencies:
+      - ./data/0.50.0/org/eolang/number.phi
+      - ./data/0.50.0/org/eolang/bytes.phi
+    input: |
+      {
+        ⟦
+          c ↦ Φ̇.number(
+            as-bytes ↦ Φ̇.bytes(
+              ⟦ Δ ⤍ 40-39-00-00-00-00-00-00 ⟧
+            )
+          ),
+          φ ↦ ξ.c.times(
+            x ↦ ⟦
+              Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
+            ⟧
+          ).plus(
+            x ↦ ⟦
+              Δ ⤍ 40-40-00-00-00-00-00-00
+            ⟧
+          )
+        ⟧
+      }
+    output:
+      object: "77.0"
+
+  - name: "Equality of booleans (via equality of bytes)"
+    dependencies:
+      - ./data/0.50.0/org/eolang/bytes.phi
+      - ./data/0.50.0/org/eolang/true.phi
+      - ./data/0.50.0/org/eolang/false.phi
+    input: |
+      {
+        ⟦
+          φ ↦ Φ̇.true.eq(α0 ↦ Φ̇.true)
+        ⟧
+      }
+    output:
+      bytes: "01-"
+
+  - name: "Program with ξ.ρ.ρ"
+    dependencies: []
+    input: |
+      {
+        ⟦
+          x ↦ ⟦
+            b ↦ ⟦
+              Δ ⤍ 01-
+            ⟧,
+            φ ↦ ⟦
+              b ↦ ⟦
+                Δ ⤍ 02-
+              ⟧,
+              c ↦ ⟦
+                a ↦ ξ.ρ.ρ.b,
+                ρ ↦ ∅
+              ⟧.a,
+              ρ ↦ ∅
+            ⟧.c,
+            ρ ↦ ∅
+          ⟧.φ,
+          λ ⤍ Package
+        ⟧
+      }
+    output:
+      object: |
+        ⟦ x ↦ ⟦ Δ ⤍ 01- ⟧, λ ⤍ Package ⟧
+
+  - name: "Preprocessing and dispatch"
+    dependencies: []
+    input: |
+      {
+        ⟦
+          a ↦ ⟦
+            b ↦ ⟦
+              Δ ⤍ 01-
+            ⟧
+          ⟧.b,
+          λ ⤍ Package
+        ⟧
+      }
+    output:
+      object: |
+        ⟦ a ↦ ⟦ Δ ⤍ 01- ⟧, λ ⤍ Package ⟧
+
+  - name: "New values in copy through ξ"
+    dependencies: []
+    input: |
+      {
+        ⟦
+          a ↦ ⟦
+            b ↦ ∅,
+            c ↦ ξ.b
+          ⟧,
+          d ↦ ξ.a(
+            b ↦ ⟦
+              Δ ⤍ 01-
+            ⟧
+          ).c,
+          λ ⤍ Package
+        ⟧
+      }
+    output:
+      object: |
+        ⟦ a ↦ ⟦ b ↦ ∅, c ↦ ξ.b ⟧, d ↦ ⟦ Δ ⤍ 01- ⟧, λ ⤍ Package ⟧
+
+  - name: "ρ-applications and stacked dispatches"
+    dependencies: []
+    input: |
+      {
+        ⟦
+          x ↦ ⟦
+            a ↦ ⟦
+              b ↦ ⟦
+                c ↦ ⟦
+                  Δ ⤍ 01-
+                ⟧
+              ⟧
+            ⟧
+          ⟧.a.b.c,
+          λ ⤍ Package
+        ⟧
+      }
+    output:
+      object: |
+        ⟦ x ↦ ⟦ Δ ⤍ 01- ⟧, λ ⤍ Package ⟧
+
+  - name: "ρ-applications and immediate dispatches"
+    dependencies: []
+    input: |
+      {
+        ⟦
+          x ↦ ⟦
+            a ↦ ⟦
+              b ↦ ⟦
+                c ↦ ⟦
+                  Δ ⤍ 01-
+                ⟧
+              ⟧.c
+            ⟧.b
+          ⟧.a,
+          λ ⤍ Package
+        ⟧
+      }
+    output:
+      object: |
+        ⟦ x ↦ ⟦ Δ ⤍ 01- ⟧, λ ⤍ Package ⟧
+
+  - name: "new values in copy through ρ"
+    dependencies: []
+    input: |
+      {
+        ⟦
+          x ↦ ⟦
+            a ↦ ⟦
+              b ↦ ξ.ρ.c
+            ⟧.b,
+            c ↦ ∅
+          ⟧,
+          d ↦ ξ.x(
+            c ↦ ⟦
+              Δ ⤍ 01-
+            ⟧
+          ).a,
+          λ ⤍ Package
+        ⟧
+      }
+    output:
+      object: |
+        ⟦ x ↦ ⟦ a ↦ ⟦ b ↦ ξ.ρ.c ⟧.b, c ↦ ∅ ⟧, d ↦ ⟦ Δ ⤍ 01- ⟧, λ ⤍ Package ⟧
+
+  - name: "ρ and nested dispatches"
+    dependencies: []
+    input: |
+      {
+        ⟦
+          x ↦ ⟦
+            a ↦ ⟦
+              b ↦ ⟦
+                c ↦ ξ.ρ
+              ⟧.c
+            ⟧.b
+          ⟧.a,
+          λ ⤍ Package
+        ⟧
+      }
+    output:
+      object: |
+        ⟦ x ↦ ⟦ b ↦ ⟦ c ↦ ξ.ρ ⟧.ρ, ρ ↦ ⟦ a ↦ ⟦ b ↦ ⟦ c ↦ ξ.ρ ⟧.ρ ⟧ ⟧ ⟧, λ ⤍ Package ⟧
+
+  - name: "usage of Φ with a loop"
+    dependencies: []
+    input: |
+      {
+        ⟦
+          a ↦ ⟦
+            b ↦ Φ.a
+          ⟧,
+          λ ⤍ Package
+        ⟧
+      }
+    output:
+      object: |
+        ⟦ a ↦ ⟦ b ↦ Φ.a ⟧, λ ⤍ Package ⟧
+
+  - name: "ρ passed to both term of object application?"
+    dependencies: []
+    input: |
+      {
+        ⟦
+          x ↦ ⟦
+            c ↦ ⟦
+              a ↦ ∅
+            ⟧(
+              a ↦ ⟦
+                d ↦ ξ.ρ
+              ⟧
+            )
+          ⟧.c,
+          λ ⤍ Package
+        ⟧
+      }
+    output:
+      object: |
+        ⟦ x ↦ ⟦
+            a ↦ ⟦
+              d ↦ ξ.ρ,
+              ρ ↦ ⟦ c ↦ ⟦ a ↦ ∅ ⟧(a ↦ ⟦ d ↦ ξ.ρ ⟧) ⟧
+            ⟧,
+            ρ ↦ ⟦ c ↦ ⟦ a ↦ ∅ ⟧(a ↦ ⟦ d ↦ ξ.ρ ⟧) ⟧
+          ⟧,
+          λ ⤍ Package
+        ⟧
+
+  - name: "Object with ξ.ρ is an argument in application"
+    dependencies: []
+    input: |
+      {
+        ⟦
+          a ↦ ⟦
+            b ↦ ∅,
+            x ↦ ⟦
+              Δ ⤍ 01-
+            ⟧
+          ⟧(
+            b ↦ ⟦
+              c ↦ ξ.ρ.x
+            ⟧
+          ).b.c,
+          x ↦ ⟦
+            Δ ⤍ 02-
+          ⟧,
+          λ ⤍ Package
+        ⟧
+      }
+    output:
+      object: |
+        ⟦ a ↦ ⟦ Δ ⤍ 02- ⟧, x ↦ ⟦ Δ ⤍ 02- ⟧, λ ⤍ Package ⟧
+
+  # TODO #636:30min hangs
+  # - name: "ξ in application"
+  #   dependencies: []
+  #   input: |
+  #     {⟦ x ↦ ⟦ a ↦ ∅ ⟧(a ↦ ξ.b), b ↦ ⟦ Δ ⤍ 01- ⟧ , λ ⤍ Package ⟧}
+  #   output:
+  #     object: |
+  #       ⟦ x ↦ ⟦
+  #           a ↦ ⟦
+  #             Δ ⤍ 01-,
+  #             ρ ↦ ⟦
+  #               b ↦ ⟦ Δ ⤍ 01- ⟧,
+  #               x ↦ ⟦ a ↦ ∅ ⟧ (a ↦ ξ.b),
+  #               λ ⤍ Package
+  #             ⟧
+  #           ⟧
+  #         ⟧,
+  #         b ↦ ⟦ Δ ⤍ 01- ⟧,
+  #         λ ⤍ Package
+  #       ⟧
+
+  - name: "ξ chain"
+    dependencies: []
+    input: |
+      {
+        ⟦
+          a ↦ ξ.b,
+          b ↦ ξ.c,
+          c ↦ ξ.d,
+          d ↦ ⟦
+            Δ ⤍ 01-
+          ⟧,
+          λ ⤍ Package
+        ⟧
+      }
+    output:
+      object: |
+        ⟦ a ↦ ⟦ Δ ⤍ 01- ⟧, b ↦ ⟦ Δ ⤍ 01- ⟧, c ↦ ⟦ Δ ⤍ 01- ⟧, d ↦ ⟦ Δ ⤍ 01- ⟧, λ ⤍ Package ⟧
+
+  # TODO #636:30min fails
+  # - name: "cross-reference (1)"
+  #   dependencies: []
+  #   input: |
+  #     {⟦ x ↦ ⟦ a ↦ ⟦ b ↦ ξ.ρ.d.e, c ↦ ⟦ Δ ⤍ 01- ⟧, ρ ↦ ∅ ⟧, d ↦ ⟦ e ↦ ξ.ρ.a.c, ρ ↦ ∅ ⟧, ρ ↦ ∅ ⟧.a.b , λ ⤍ Package ⟧}
+  #   output:
+  #     object: |
+  #       NOT ⟦ x ↦ ⊥, λ ⤍ Package ⟧
+
+  # TODO #636:30min fails
+  # - name: "cross-reference (2)"
+  #   dependencies: []
+  #   input: |
+  #     {⟦ x ↦ ⟦ a ↦ ⟦ b ↦ ξ.ρ.d.e, c ↦ ξ.ρ.d.f ⟧, d ↦ ⟦ e ↦ ξ.ρ.a.c, f ↦ ⟦ Δ ⤍ 01- ⟧ ⟧ ⟧.a.b , λ ⤍ Package ⟧}
+  #   output:
+  #     object: |
+  #       NOT ⟦ x ↦ ⊥, λ ⤍ Package ⟧
+
+  # TODO #636:30min fails
+  # - name: "cross-reference + dispatch (1)"
+  #   dependencies: []
+  #   input: |
+  #     {⟦ x ↦ ⟦ a ↦ ⟦ b ↦ ξ.ρ.d, c ↦ ⟦ Δ ⤍ 01- ⟧ ⟧, d ↦ ⟦ e ↦ ξ.ρ.a.c ⟧ ⟧.a.b.e , λ ⤍ Package ⟧}
+  #   output:
+  #     object: |
+  #       NOT ⟦ x ↦ ⊥, λ ⤍ Package ⟧
+
+  # TODO #636:30min fails
+  # - name: "cross-reference + dispatch (1)"
+  #   dependencies: []
+  #   input: |
+  #     {⟦ x ↦ ⟦ a ↦ ⟦ b ↦ ξ.ρ.d, c ↦ ⟦ Δ ⤍ 01- ⟧ ⟧, d ↦ ⟦ e ↦ ξ.ρ.a.c ⟧ ⟧.a.b.e , λ ⤍ Package ⟧}
+  #   output:
+  #     object: |
+  #       NOT ⟦ x ↦ ⊥, λ ⤍ Package ⟧
+
+  # TODO #636:30min fails
+  # - name: "cross-reference + dispatch (2)"
+  #   dependencies: []
+  #   input: |
+  #     {⟦ x ↦ ⟦ a ↦ ⟦ b ↦ ξ.ρ.d, c ↦ ξ.ρ.d.f ⟧, d ↦ ⟦ e ↦ ξ.ρ.a.c, f ↦ ⟦ Δ ⤍ 01- ⟧ ⟧ ⟧.a.b.e , λ ⤍ Package ⟧}
+  #   output:
+  #     object: |
+  #       NOT ⟦ x ↦ ⊥, λ ⤍ Package ⟧
+
+  # TODO #636:30min fails
+  # - name: "cross-reference + dispatch (3)"
+  #   dependencies: []
+  #   input: |
+  #     {⟦ x ↦ ⟦ a ↦ ⟦ b ↦ ξ.ρ.d, c ↦ ξ.ρ.d ⟧, d ↦ ⟦ e ↦ ξ.ρ.a.c, f ↦ ⟦ Δ ⤍ 01- ⟧ ⟧ ⟧.a.b.e.f , λ ⤍ Package ⟧}
+  #   output:
+  #     object: |
+  #       NOT ⟦ x ↦ ⊥, λ ⤍ Package ⟧
+
+  # TODO #636:30min fails
+  # - name: "interleaving ρ and other dispatches"
+  #   dependencies: []
+  #   input: |
+  #     {⟦ x ↦ ⟦ a ↦ ξ.ρ.b.ρ.c ⟧.a, b ↦ ⟦⟧, c ↦ ⟦ Δ ⤍ 01- ⟧, λ ⤍ Package ⟧}
+  #   output:
+  #     object: |
+  #       NOT ⟦ x ↦ ⟦ ⟧.ρ.b.ρ.c, b ↦ ⟦ ⟧, c ↦ ⟦ Δ ⤍ 01- ⟧, λ ⤍ Package ⟧
+
+  - name: "Dataize in siblings of Package"
+    dependencies:
+      - ./data/0.50.0/org/eolang/bytes.phi
+    input: |
+      {
+        ⟦
+          org ↦ ⟦
+            eolang ↦ ⟦
+              bool ↦ ⟦
+                α0 ↦ ∅,
+                φ ↦ ξ.α0
+              ⟧,
+              x ↦ ⟦
+                φ ↦ Φ̇.bool(
+                  Φ̇.bytes(
+                    ⟦ Δ ⤍ 01- ⟧
+                  )
+                )
+              ⟧,
+              z ↦ ⟦
+                y ↦ ⟦
+                  x ↦ ∅,
+                  φ ↦ ξ.x
+                ⟧,
+                φ ↦ Φ̇.bool(
+                  Φ̇.bytes(
+                    ⟦ Δ ⤍ 01- ⟧
+                  )
+                )
+              ⟧,
+              λ ⤍ Package
+            ⟧,
+            λ ⤍ Package
+          ⟧,
+          λ ⤍ Package
+        ⟧
+      }
+    output:
+      object: |
+        ⟦
+          org ↦ ⟦
+            eolang ↦ ⟦
+              bool ↦ ⟦ α0 ↦ ∅, φ ↦ ξ.α0 ⟧,
+              x ↦ ⟦ Δ ⤍ 01- ⟧,
+              z ↦ ⟦ Δ ⤍ 01- ⟧,
+              λ ⤍ Package
+            ⟧,
+            λ ⤍ Package
+          ⟧,
+          λ ⤍ Package
+        ⟧
+
+  - name: "int times and plus"
+    dependencies:
+      - ./data/0.50.0/org/eolang/i64.phi
+      - ./data/0.50.0/org/eolang/bytes.phi
+    input: |
+      {
+        ⟦
+          φ ↦ ⟦
+            x ↦ ⟦
+              x ↦ ⟦
+                Δ ⤍ 09-
+              ⟧,
+              ρ ↦ ⟦
+                Δ ⤍ 04-
+              ⟧,
+              λ ⤍ Lorg_eolang_int_times
+            ⟧,
+            ρ ↦ ⟦
+              Δ ⤍ 06-
+            ⟧,
+            λ ⤍ Lorg_eolang_int_plus
+          ⟧
+        ⟧
+      }
+    output:
+      object: "42"
+
+  - name: "int greater than"
+    dependencies:
+      - ./data/0.50.0/org/eolang/i64.phi
+      - ./data/0.50.0/org/eolang/bytes.phi
+      - ./data/0.50.0/org/eolang/false.phi
+      - ./data/0.50.0/org/eolang/true.phi
+    input: |
+      {
+        ⟦
+          φ ↦ ⟦
+            ρ ↦ ⟦
+              Δ ⤍ 06-
+            ⟧,
+            x ↦ ⟦
+              Δ ⤍ 09-
+            ⟧,
+            λ ⤍ Lorg_eolang_int_gt
+          ⟧
+        ⟧
+      }
+    output:
+      bytes: "00-"
+
+  # TODO #636:30min Missing int tests: div
+
+  - name: "bitwise and"
+    dependencies:
+      - ./data/0.50.0/org/eolang/bytes.phi
+    input: |
+      {
+        ⟦
+          φ ↦ ⟦
+            b ↦ ⟦
+              Δ ⤍ 15-
+            ⟧,
+            ρ ↦ ⟦
+              Δ ⤍ 0D-
+            ⟧,
+            λ ⤍ Lorg_eolang_bytes_and
+          ⟧
+        ⟧
+      }
+    output:
+      bytes: "00-00-00-00-00-00-00-05"
+
+  - name: "bitwise not"
+    dependencies:
+      - ./data/0.50.0/org/eolang/bytes.phi
+    input: |
+      {
+        ⟦
+          φ ↦ ⟦
+            ρ ↦ ⟦
+              Δ ⤍ 50-3D-10-C0-6F-12-42-69
+            ⟧,
+            λ ⤍ Lorg_eolang_bytes_not
+          ⟧
+        ⟧
+      }
+    output:
+      bytes: "AF-C2-EF-3F-90-ED-BD-96"
+
+  - name: "bytes size"
+    dependencies:
+      - ./data/0.50.0/org/eolang/i64.phi
+      - ./data/0.50.0/org/eolang/bytes.phi
+    input: |
+      {
+        ⟦
+          φ ↦ ⟦
+            ρ ↦ ⟦
+              Δ ⤍ 00-11-22-33-44
+            ⟧,
+            λ ⤍ Lorg_eolang_bytes_size
+          ⟧
+        ⟧
+      }
+    output:
+      bytes: "00-00-00-00-00-00-00-05"
+
+  - name: "bytes shift and equal"
+    dependencies:
+      - ./data/0.50.0/org/eolang/bytes.phi
+      - ./data/0.50.0/org/eolang/true.phi
+      - ./data/0.50.0/org/eolang/i64.phi
+      - ./data/0.50.0/org/eolang/false.phi
+    input: |
+      {
+        ⟦
+          φ ↦ ⟦
+            ρ ↦ ⟦
+              Δ ⤍ 02-24-46-68-8A-AC-CE-F1
+            ⟧,
+            b ↦ ⟦
+              ρ ↦ ⟦
+                Δ ⤍ 11-22-33-44-55-66-77-88
+              ⟧,
+              x ↦ 3,
+              λ ⤍ Lorg_eolang_bytes_right
+            ⟧,
+            λ ⤍ Lorg_eolang_bytes_eq
+          ⟧
+        ⟧
+      }
+    output:
+      bytes: "01-"
+
+  # TODO #636:30min Missing bytes tests: or, xor, slice, concat
+
+  - name: "float times and plus (raw bytes)"
+    dependencies:
+      - ./data/0.50.0/org/eolang/number.phi
+      - ./data/0.50.0/org/eolang/bytes.phi
+    input: |
+      {
+        ⟦
+          φ ↦ ⟦
+            x ↦ ⟦
+              x ↦ ⟦
+                Δ ⤍ 40-14-00-00-00-00-00-00
+              ⟧,
+              ρ ↦ ⟦
+                Δ ⤍ 40-2A-66-66-66-66-66-66
+              ⟧,
+              λ ⤍ Lorg_eolang_number_times
+            ⟧,
+            ρ ↦ ⟦
+              Δ ⤍ 40-0B-5C-28-F5-C2-8F-5C
+            ⟧,
+            λ ⤍ Lorg_eolang_number_plus
+          ⟧
+        ⟧
+      }
+    output:
+      object: "69.42"
+
+  - name: "float times and plus"
+    dependencies:
+      - ./data/0.50.0/org/eolang/number.phi
+      - ./data/0.50.0/org/eolang/bytes.phi
+    input: |
+      {
+        ⟦
+          φ ↦ ⟦
+            x ↦ ⟦
+              x ↦ 5.0,
+              ρ ↦ 13.2,
+              λ ⤍ Lorg_eolang_number_times
+            ⟧,
+            ρ ↦ 3.42,
+            λ ⤍ Lorg_eolang_number_plus
+          ⟧
+        ⟧
+      }
+    output:
+      object: "69.42"
+
+  # TODO #636:30min Missing float tests: gt, div
+
+  - name: "string slice (raw bytes)"
+    dependencies:
+      - ./data/0.50.0/org/eolang/string.phi
+      - ./data/0.50.0/org/eolang/bytes.phi
+    input: |
+      {
+        ⟦
+          φ ↦ ⟦
+            start ↦ ⟦
+              Δ ⤍ 40-00-00-00-00-00-00-00
+            ⟧,
+            len ↦ ⟦
+              Δ ⤍ 40-14-00-00-00-00-00-00
+            ⟧,
+            ρ ↦ ⟦
+              Δ ⤍ 48-65-6C-6C-6F-20-77-6F-72-6C-64
+            ⟧,
+            λ ⤍ Lorg_eolang_string_slice
+          ⟧
+        ⟧
+      }
+    output:
+      object: "\"llo w\""
+
+  - name: "string slice"
+    dependencies:
+      - ./data/0.50.0/org/eolang/string.phi
+      - ./data/0.50.0/org/eolang/i64.phi
+      - ./data/0.50.0/org/eolang/bytes.phi
+    input: |
+      {
+        ⟦
+          φ ↦ ⟦
+            start ↦ 2.0,
+            len ↦ 5.0,
+            ρ ↦ "Hello world",
+            λ ⤍ Lorg_eolang_string_slice
+          ⟧
+        ⟧
+      }
+    output:
+      object: "\"llo w\""
+
+  - name: "string length (raw bytes)"
+    dependencies:
+      - ./data/0.50.0/org/eolang/string.phi
+      - ./data/0.50.0/org/eolang/i64.phi
+      - ./data/0.50.0/org/eolang/bytes.phi
+    input: |
+      {
+        ⟦
+          φ ↦ ⟦
+            ρ ↦ ⟦
+              Δ ⤍ 48-65-6C-6C-6F-20-77-6F-72-6C-64
+            ⟧,
+            λ ⤍ Lorg_eolang_string_length
+          ⟧
+        ⟧
+      }
+    output:
+      object: "11" # == 11
+
+  - name: "string length"
+    dependencies:
+      - ./data/0.50.0/org/eolang/string.phi
+      - ./data/0.50.0/org/eolang/i64.phi
+      - ./data/0.50.0/org/eolang/bytes.phi
+    input: |
+      {
+        ⟦
+          φ ↦ ⟦
+            ρ ↦ "Hello world",
+            λ ⤍ Lorg_eolang_string_length
+          ⟧
+        ⟧
+      }
+    output:
+      object: "11" # == 11
+
+  # TODO #636:30min Missing malloc tests: (all)
+
+  # TODO #636:30min Missing cage tests: (all)
+
+  # TODO #636:30min Missing io tests: (all)
+
+  # TODO #636:30min Other missing tests: dataized, error, seq, as_phi, rust, try
diff --git a/test/eo/phi/from-eo/as-phi.yaml b/test/eo/phi/from-eo/as-phi.yaml
new file mode 100644
--- /dev/null
+++ b/test/eo/phi/from-eo/as-phi.yaml
@@ -0,0 +1,76 @@
+# The MIT License (MIT)
+
+# Copyright (c) 2016-2024 Objectionary.com
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+title: Processing terms generated from EO
+tests:
+  - name: "A program that prints itself"
+    input: |
+      {⟦org ↦ ⟦eolang ↦ ⟦prints-itself ↦ ⟦φ ↦ Φ.org.eolang.as-phi(α0 ↦ ξ).length.gt(α0 ↦ Φ.org.eolang.int(α0 ↦ Φ.org.eolang.bytes(Δ ⤍ 00-00-00-00-00-00-00-00)))⟧, prints-itself-to-console ↦ ⟦x ↦ Φ.org.eolang.int(α0 ↦ Φ.org.eolang.bytes(Δ ⤍ 00-00-00-00-00-00-00-2A)), φ ↦ Φ.org.eolang.io.stdout(α0 ↦ Φ.org.eolang.as-phi(α0 ↦ ξ))⟧, λ ⤍ Package⟧, λ ⤍ Package⟧⟧}
+    normalized: |
+      { ⟦ org ↦ ⟦ eolang ↦ ⟦ prints-itself ↦ ⟦ φ ↦ Φ.org.eolang.as-phi (α0 ↦ ξ).length.gt (α0 ↦ Φ.org.eolang.int (α0 ↦ Φ.org.eolang.bytes (Δ ⤍ 00-00-00-00-00-00-00-00))) ⟧, prints-itself-to-console ↦ ⟦ x ↦ Φ.org.eolang.int (α0 ↦ Φ.org.eolang.bytes (Δ ⤍ 00-00-00-00-00-00-00-2A)), φ ↦ Φ.org.eolang.io.stdout (α0 ↦ Φ.org.eolang.as-phi (α0 ↦ ξ)) ⟧, λ ⤍ Package ⟧, λ ⤍ Package ⟧ ⟧ }
+    prettified: |
+      {
+        ⟦
+          org ↦ ⟦
+            eolang ↦ ⟦
+              prints-itself ↦ ⟦
+                φ ↦ Φ̇.as-phi(
+                  ξ
+                ).length.gt(
+                  Φ̇.int(
+                    Φ̇.bytes(
+                      Δ ⤍ 00-00-00-00-00-00-00-00
+                    )
+                  )
+                )
+              ⟧,
+              prints-itself-to-console ↦ ⟦
+                x ↦ Φ̇.int(
+                  Φ̇.bytes(
+                    Δ ⤍ 00-00-00-00-00-00-00-2A
+                  )
+                ),
+                φ ↦ Φ̇.io.stdout(
+                  Φ̇.as-phi(
+                    ξ
+                  )
+                )
+              ⟧,
+              λ ⤍ Package
+            ⟧,
+            λ ⤍ Package
+          ⟧
+        ⟧
+      }
+  - name: "Prints empty parentheses"
+    input: |
+      {⟦ m ↦ ⟦ x ↦ ⟦ ⟧ ⟧() ⟧}
+    normalized: |
+      {⟦ m ↦ ⟦ x ↦ ⟦ ⟧ ⟧() ⟧}
+    prettified: |
+      {
+        ⟦
+          m ↦ ⟦
+            x ↦ ⟦⟧
+          ⟧()
+        ⟧
+      }
diff --git a/test/eo/phi/metrics.yaml b/test/eo/phi/metrics.yaml
new file mode 100644
--- /dev/null
+++ b/test/eo/phi/metrics.yaml
@@ -0,0 +1,81 @@
+# The MIT License (MIT)
+
+# Copyright (c) 2016-2024 Objectionary.com
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+title: Metrics tests
+tests:
+- title: prints-itself
+  phi: |
+    {
+      ⟦
+        org ↦ ⟦
+          eolang ↦ ⟦
+            prints-itself ↦ ⟦
+              φ ↦
+                Φ.org.eolang.as-phi(
+                  α0 ↦ ξ
+                ).length.gt(
+                  α0 ↦ Φ.org.eolang.int(
+                    α0 ↦ Φ.org.eolang.bytes(
+                      Δ ⤍ 00-00-00-00-00-00-00-00
+                    )
+                  )
+                )
+            ⟧,
+            prints-itself-to-console ↦ ⟦
+              x ↦ Φ.org.eolang.int(
+                α0 ↦ Φ.org.eolang.bytes(
+                  Δ ⤍ 00-00-00-00-00-00-00-2A
+                )
+              ),
+              φ ↦ Φ.org.eolang.io.stdout(
+                α0 ↦ Φ.org.eolang.as-phi(
+                  α0 ↦ ξ
+                )
+              )
+            ⟧,
+            λ ⤍ Package
+          ⟧,
+          λ ⤍ Package
+        ⟧
+      ⟧
+    }
+  metrics:
+    program-metrics:
+      dataless: 5
+      applications: 8
+      formations: 5
+      dispatches: 24
+    bindings-by-path-metrics:
+      path: org.eolang
+      bindings-metrics:
+        - name: prints-itself
+          metrics:
+            dataless: 1
+            applications: 4
+            formations: 1
+            dispatches: 11
+        - name: prints-itself-to-console
+          metrics:
+            dataless: 1
+            applications: 4
+            formations: 1
+            dispatches: 13
diff --git a/test/eo/phi/rewriting.yaml b/test/eo/phi/rewriting.yaml
new file mode 100644
--- /dev/null
+++ b/test/eo/phi/rewriting.yaml
@@ -0,0 +1,120 @@
+# The MIT License (MIT)
+
+# Copyright (c) 2016-2024 Objectionary.com
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+title: "Rewriting tests (integration tests)"
+tests:
+# TODO #655:10m Enable
+# - name: e-alph
+#   input: |
+#     {⟦ k ↦ ⟦ x ↦ ∅ ⟧ ( α0 ↦ ⟦ Δ ⤍ 42- ⟧ ).x ⟧}
+#   output: |
+#     {⟦ k ↦ ⟦ Δ ⤍ 42- ⟧ ⟧}
+# - name: e-fnk
+#   input: |
+#     {⟦ m ↦ ⟦ x ↦ ⟦ t ↦ ∅ ⟧ (t ↦ ξ.k), k ↦ ⟦ λ ⤍ Fn ⟧ ⟧.x.t.p ⟧}
+#   output: |
+#     {⟦ m ↦ ⟦ λ ⤍ Fn, ρ ↦ ⟦ x ↦ ⟦ t ↦ ∅ ⟧ (t ↦ ξ.k), k ↦ ⟦ λ ⤍ Fn ⟧ ⟧ ⟧.p ⟧}
+- name: e-ald
+  input: |
+    {⟦ k ↦ ⟦ x ↦ ∅ ⟧ ( α1 ↦ ⟦ Δ ⤍ 42- ⟧ ).x ⟧}
+  output: |
+    {⟦ k ↦ ⊥ ⟧}
+- name: e-app
+  input: |
+    {⟦ k ↦ ⟦ x ↦ ξ.t, t ↦ ∅ ⟧ (t ↦ ⟦ Δ ⤍ 42- ⟧) ⟧}
+  output: |
+    {⟦ k ↦ ⟦ t ↦ ⟦ Δ ⤍ 42- ⟧, x ↦ ξ.t ⟧ ⟧}
+- name: e-cpy
+  input: |
+    {⟦ m ↦ ⟦ x ↦ ∅, y ↦ ξ.x ⟧ (x ↦ ⟦ Δ ⤍ 42- ⟧).y ⟧}
+  output: |
+    { ⟦ m ↦ ⟦ ρ ↦ ⟦ x ↦ ⟦ Δ ⤍ 42- ⟧, y ↦ ξ.x ⟧, Δ ⤍ 42- ⟧ ⟧}
+- name: e-int
+  input: |
+    {⟦ m ↦ ⟦ x ↦ ⟦ t ↦ ⟦ Δ ⤍ 42- ⟧ ⟧.t ⟧.x ⟧}
+  output: |
+    {⟦ m ↦ ⟦ ρ ↦ ⟦ t ↦ ⟦ Δ ⤍ 42- ⟧ ⟧, Δ ⤍ 42- ⟧ ⟧}
+- name: e-lam
+  input: |
+    {⟦ m ↦ ⟦ x ↦ ⟦ λ ⤍ Fn ⟧.ρ.k, k ↦ ⟦ Δ ⤍ 42- ⟧ ⟧.x ⟧}
+  output: |
+    {⟦ m ↦ ⟦ λ ⤍ Fn ⟧.ρ.k(ρ ↦ ⟦ x ↦ ⟦ λ ⤍ Fn ⟧.ρ.k, k ↦ ⟦ Δ ⤍ 42- ⟧ ⟧ ) ⟧}
+- name: e-nf
+  input: |
+    {⟦ x ↦ ⟦ t ↦ Φ.x ⟧ ⟧}
+  output: |
+    {⟦ x ↦ ⟦ t ↦ Φ.x ⟧ ⟧}
+- name: e-nk
+  input: |
+    {⟦ x ↦ ξ.k, k ↦ ⟦ Δ ⤍ 42- ⟧ ⟧}
+  output: |
+    {⟦ x ↦ ξ.k, k ↦ ⟦ Δ ⤍ 42- ⟧ ⟧}
+- name: e-np
+  input: |
+    {⟦ x ↦ ξ.t, λ ⤍ Fn ⟧}
+  output: |
+    {⟦ x ↦ ξ.t, λ ⤍ Fn ⟧}
+- name: e-nr
+  input: |
+    {⟦ x ↦ ξ.k, t ↦ ⟦ Δ ⤍ 42- ⟧ ⟧}
+  output: |
+    {⟦ x ↦ ξ.k, t ↦ ⟦ Δ ⤍ 42- ⟧ ⟧}
+- name: e-nt
+  input: |
+    {⟦ m ↦ ⟦ x ↦ ⟦ Δ ⤍ 42- ⟧, λ ⤍ Fn ⟧.y ⟧}
+  output: |
+    {⟦ m ↦ ⟦ x ↦ ⟦ Δ ⤍ 42- ⟧, λ ⤍ Fn ⟧.y ⟧}
+- name: e-phi
+  input: |
+    {⟦ m ↦ ⟦ x ↦ ξ.t, φ ↦ ⟦ t ↦ ⟦⟧ ⟧ ⟧.x ⟧}
+  output: |
+    {⟦ m ↦ ⟦ ρ ↦ ⟦ t ↦ ⟦ ⟧, ρ ↦ ⟦ φ ↦ ⟦ t ↦ ⟦ ⟧ ⟧, x ↦ ξ.t ⟧ ⟧ ⟧ ⟧}
+- name: e-rep
+  input: |
+    {⟦ m ↦ ⟦ x ↦ ξ.t (k ↦ ξ.f).k, t ↦ ⟦ k ↦ ∅ ⟧, f ↦ ⟦⟧ ⟧.x ⟧}
+  output: |
+    {⟦ m ↦ ⟦ ρ ↦ ⟦f ↦ ⟦⟧, x ↦ ξ.t (k ↦ ξ.f).k, t ↦ ⟦k ↦ ∅⟧ ⟧ ⟧ ⟧}
+- name: e-rha
+  input: |
+    {⟦ m ↦ ⟦ x ↦ ⟦ ρ ↦ ∅ ⟧.ρ.k, k ↦ ⟦ Δ ⤍ 42- ⟧ ⟧.x ⟧}
+  output: |
+    {⟦ m ↦ ⊥ ⟧}
+- name: e-rhi
+  input: |
+    {⟦ m ↦ ⟦ x ↦ ⟦ t ↦ ⟦ p ↦ ξ.ρ.ρ.k ⟧.p ⟧.t, k ↦ ⟦ Δ ⤍ 42- ⟧ ⟧.x ⟧}
+  output: |
+    {⟦ m ↦ ⊥ ⟧}
+- name: e-rho
+  input: |
+    {⟦ m ↦ ⟦ x ↦ ξ.ρ.ρ.t ⟧.x ⟧}
+  output: |
+    {⟦ m ↦ ⊥ ⟧}
+- name: e-twi
+  input: |
+    {⟦ m ↦ ⟦ x ↦ ⟦ t ↦ ξ.ρ.k.ρ.t ⟧, k ↦ ⟦⟧, t ↦ ⟦⟧ ⟧.x.t ⟧}
+  output: |
+    { ⟦ m ↦ ⟦ ρ ↦ ⟦ t ↦ ⟦ ⟧, ρ ↦ ⟦ ρ ↦ ⟦ x ↦ ⟦ t ↦ ξ.ρ.k.ρ.t ⟧, k ↦ ⟦ ⟧, t ↦ ⟦ ⟧ ⟧, t ↦ ξ.ρ.k.ρ.t ⟧, k ↦ ⟦ ⟧, x ↦ ⟦ t ↦ ξ.ρ.k.ρ.t ⟧ ⟧ ⟧ ⟧}
+- name: e-xxi
+  input: |
+    {⟦ m ↦ ⟦ x ↦ ξ.t, t ↦ ∅ ⟧.x ⟧}
+  output: |
+    {⟦ m ↦ ⊥ ⟧}
