diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -127,11 +127,12 @@
 ```
 
 Configuration files can be used globally or per project. By default, `hadolint` will look for
-a configuration file in the current directory with the name `.hadolint.yaml`
+a configuration file in the current directory with the name `.hadolint.yaml` or
+`.hadolint.yml`
 
 The global configuration file should be placed in the folder specified by `XDG_CONFIG_HOME`,
-with the name `hadolint.yaml`. In summary, the following locations are valid for the configuration
-file, in order or preference:
+with the name `hadolint.yaml` or `hadolint.yml`. In summary, the following locations are valid
+for the configuration file, in order or preference:
 
 - `$PWD/.hadolint.yaml`
 - `$XDG_CONFIG_HOME/hadolint.yaml`
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -1,11 +1,12 @@
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TemplateHaskell #-}
 
 module Main where
 
 import Control.Applicative
+import Control.Monad (when)
 import qualified Data.Bifunctor as Bifunctor
 import qualified Data.List.NonEmpty as NonEmpty
 import qualified Data.Map as Map
@@ -17,9 +18,11 @@
 import qualified Data.Version
 import qualified Development.GitRev
 import qualified Hadolint
+import qualified Hadolint.Formatter.Format as Format
 import qualified Hadolint.Rule as Rule
 import Options.Applicative
   ( Parser,
+    ReadM,
     action,
     argument,
     completeWith,
@@ -35,7 +38,6 @@
     metavar,
     option,
     progDesc,
-    ReadM,
     short,
     showDefaultWith,
     str,
@@ -47,12 +49,14 @@
 import qualified Paths_hadolint as Meta
 import System.Environment
 import System.Exit (exitFailure, exitSuccess)
+import System.IO (hPutStrLn, stderr)
 
 data CommandOptions = CommandOptions
   { showVersion :: Bool,
     noFail :: Bool,
     nocolor :: Bool,
     configFile :: Maybe FilePath,
+    isVerbose :: Bool,
     format :: Hadolint.OutputFormat,
     dockerfiles :: [String],
     lintingOptions :: Hadolint.LintOptions
@@ -75,6 +79,15 @@
 showFormat Hadolint.Checkstyle = "checkstyle"
 showFormat Hadolint.Codacy = "codacy"
 
+toNofailSeverity :: String -> Maybe Rule.DLSeverity
+toNofailSeverity "error" = Just Rule.DLErrorC
+toNofailSeverity "warning" = Just Rule.DLWarningC
+toNofailSeverity "info" = Just Rule.DLInfoC
+toNofailSeverity "style" = Just Rule.DLStyleC
+toNofailSeverity "ignore" = Just Rule.DLIgnoreC
+toNofailSeverity "none" = Just Rule.DLIgnoreC
+toNofailSeverity _ = Nothing
+
 parseOptions :: Parser CommandOptions
 parseOptions =
   CommandOptions
@@ -82,6 +95,7 @@
     <*> noFail
     <*> nocolor
     <*> configFile
+    <*> isVerbose
     <*> outputFormat
     <*> files
     <*> lintOptions
@@ -90,10 +104,28 @@
 
     noFail = switch (long "no-fail" <> help "Don't exit with a failure status code when any rule is violated")
 
+    noFailCutoff =
+      option
+        (maybeReader toNofailSeverity)
+        ( short 't'
+            <> long "failure-theshold"
+            <> help
+              "Exit with failure code only when rules with a severity \
+              \above THRESHOLD are violated. Accepted values: \
+              \[error | warning | info | style | ignore | none]"
+            <> value Rule.DLInfoC
+            <> metavar "THRESHOLD"
+            <> showDefaultWith (Text.unpack . Format.severityText)
+            <> completeWith ["error", "warning", "info", "style", "ignore", "none"]
+        )
+
     nocolor = switch (long "no-color" <> help "Don't colorize output")
 
-    strictlabels = switch (long "strict-labels"
-        <> help "Do not permit labels other than specified in `label-schema`")
+    strictlabels =
+      switch
+        ( long "strict-labels"
+            <> help "Do not permit labels other than specified in `label-schema`"
+        )
 
     configFile =
       optional
@@ -103,6 +135,8 @@
             )
         )
 
+    isVerbose = switch (long "verbose" <> short 'V' <> help "Enables verbose logging of hadolint's output to stderr")
+
     outputFormat =
       option
         (maybeReader toOutputFormat)
@@ -170,10 +204,13 @@
         <*> styleList
         <*> ignoreList
         <*> parseRulesConfig
+        <*> noFailCutoff
 
-    labels = Map.fromList
+    labels =
+      Map.fromList
         <$> many
-          ( option readSingleLabelSchema
+          ( option
+              readSingleLabelSchema
               ( long "require-label"
                   <> help "The option --require-label=label:format makes Hadolint check that the label `label` conforms to format requirement `format`"
                   <> metavar "LABELSCHEMA (e.g. maintainer:text)"
@@ -186,7 +223,8 @@
         <*> labels
         <*> strictlabels
 
-    parseAllowedRegistries = Set.fromList . fmap fromString
+    parseAllowedRegistries =
+      Set.fromList . fmap fromString
         <$> many
           ( strOption
               ( long "trusted-registry"
@@ -202,19 +240,26 @@
 
 labelParser :: Text.Text -> Either String (Rule.LabelName, Rule.LabelType)
 labelParser l =
-    case Bifunctor.second (Rule.read . Text.drop 1) $ Text.breakOn ":" l of
-      (ln, Right lt) -> Right (ln, lt)
-      (_, Left e) -> Left $ Text.unpack e
+  case Bifunctor.second (Rule.read . Text.drop 1) $ Text.breakOn ":" l of
+    (ln, Right lt) -> Right (ln, lt)
+    (_, Left e) -> Left $ Text.unpack e
 
-noFailure :: Hadolint.Result s e -> Bool
-noFailure (Hadolint.Result _ Seq.Empty Seq.Empty) = True
-noFailure _ = False
+noFailure :: Hadolint.Result s e -> Rule.DLSeverity -> Bool
+noFailure (Hadolint.Result _ Seq.Empty Seq.Empty) _ = True
+noFailure (Hadolint.Result _ Seq.Empty fails) cutoff =
+  Seq.null (Seq.filter (\f -> Rule.severity f < cutoff) fails)
+noFailure _ _ = False
 
-exitProgram :: Foldable f => CommandOptions -> f (Hadolint.Result s e) -> IO ()
-exitProgram cmd res
+exitProgram ::
+  Foldable f =>
+  CommandOptions ->
+  Hadolint.LintOptions ->
+  f (Hadolint.Result s e) ->
+  IO ()
+exitProgram cmd conf res
   | noFail cmd = exitSuccess
   | Hadolint.shallSkipErrorStatus (format cmd) = exitSuccess
-  | all noFailure res = exitSuccess
+  | all (`noFailure` Hadolint.failThreshold conf) res = exitSuccess
   | otherwise = exitFailure
 
 runLint :: CommandOptions -> Hadolint.LintOptions -> NonEmpty.NonEmpty String -> IO ()
@@ -223,7 +268,7 @@
   noColorEnv <- lookupEnv "NO_COLOR"
   let noColor = nocolor cmd || isJust noColorEnv
   Hadolint.printResults (format cmd) noColor res
-  exitProgram cmd res
+  exitProgram cmd conf res
 
 main :: IO ()
 main = do
@@ -234,7 +279,9 @@
     execute CommandOptions {dockerfiles = []} =
       putStrLn "Please provide a Dockerfile" >> exitFailure
     execute cmd = do
-      lintConfig <- Hadolint.applyConfig (configFile cmd) (lintingOptions cmd)
+      maybeConfig <- Hadolint.getConfig (configFile cmd)
+      when (isVerbose cmd) (hPutStrLn stderr $ getFilePathDescription maybeConfig)
+      lintConfig <- Hadolint.applyConfig maybeConfig (lintingOptions cmd)
       let files = NonEmpty.fromList (dockerfiles cmd)
       case lintConfig of
         Left err -> error err
@@ -253,3 +300,7 @@
   | otherwise = "Haskell Dockerfile Linter " ++ version
   where
     version = $(Development.GitRev.gitDescribe)
+
+getFilePathDescription :: Maybe FilePath -> String
+getFilePathDescription Nothing = "No configuration was specified. Using default configuration"
+getFilePathDescription (Just filepath) = "Configuration file used: " ++ filepath
diff --git a/hadolint.cabal b/hadolint.cabal
--- a/hadolint.cabal
+++ b/hadolint.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 76044842a02febfc721b4776d4e4bbfdb11c9327f25de10eca894d0d19c1af6b
+-- hash: 0122b347f3d7e60bbead61f38f32acd69b57e1794597b5243bb2b6cabf2a358f
 
 name:           hadolint
-version:        2.3.0
+version:        2.4.0
 synopsis:       Dockerfile Linter JavaScript API
 description:    A smarter Dockerfile linter that helps you build best practice Docker images.
 category:       Development
@@ -137,7 +137,7 @@
     , filepath
     , foldl
     , ilist
-    , language-docker >=9.3.0 && <10
+    , language-docker >=10.0.0 && <11
     , megaparsec >=9.0.0
     , mtl
     , network-uri
@@ -158,14 +158,14 @@
       Paths_hadolint
   hs-source-dirs:
       app
-  default-extensions: OverloadedStrings NamedFieldPuns DeriveGeneric DeriveAnyClass RecordWildCards StrictData ScopedTypeVariables PatternSynonyms
+  default-extensions: OverloadedStrings NamedFieldPuns DeriveGeneric DeriveAnyClass RecordWildCards StrictData ScopedTypeVariables PatternSynonyms TemplateHaskell
   ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -optP-Wno-nonportable-include-path -flate-dmd-anal -O2 -threaded -rtsopts "-with-rtsopts=-N5 -A4m"
   build-depends:
       base >=4.8 && <5
     , containers
     , gitrev >=1.3.1
     , hadolint
-    , language-docker >=9.3.0 && <10
+    , language-docker >=10.0.0 && <11
     , megaparsec >=9.0.0
     , optparse-applicative >=0.14.0
     , text
@@ -264,7 +264,7 @@
     , foldl
     , hadolint
     , hspec
-    , language-docker >=9.3.0 && <10
+    , language-docker >=10.0.0 && <11
     , megaparsec >=9.0.0
     , split >=0.2
     , text
diff --git a/src/Hadolint/Config.hs b/src/Hadolint/Config.hs
--- a/src/Hadolint/Config.hs
+++ b/src/Hadolint/Config.hs
@@ -1,5 +1,6 @@
 module Hadolint.Config
   ( applyConfig,
+    getConfig,
     ConfigFile (..),
     OverrideConfig (..),
   )
@@ -47,17 +48,22 @@
     ignoredRules :: Maybe [Lint.IgnoreRule],
     trustedRegistries :: Maybe [Lint.TrustedRegistry],
     labelSchemaConfig :: Maybe Rule.LabelSchema,
-    strictLabelSchema :: Maybe Bool
+    strictLabelSchema :: Maybe Bool,
+    failureThreshold :: Maybe Rule.DLSeverity
   }
   deriving (Show, Eq, Generic)
 
 instance Yaml.FromYAML OverrideConfig where
-  parseYAML = Yaml.withMap "OverrideConfig" $ \m ->
-    OverrideConfig
-      <$> m .:? "error"
-      <*> m .:? "warning"
-      <*> m .:? "info"
-      <*> m .:? "style"
+  parseYAML = Yaml.withMap "OverrideConfig" $ \m -> do
+    err <- m .:? "error"
+    wrn <- m .:? "warning"
+    inf <- m .:? "info"
+    sty <- m .:? "style"
+    let overrideErrorRules = coerce (err :: Maybe [Text.Text])
+        overrideWarningRules = coerce (wrn :: Maybe [Text.Text])
+        overrideInfoRules = coerce (inf :: Maybe [Text.Text])
+        overrideStyleRules = coerce (sty:: Maybe [Text.Text])
+    return OverrideConfig {..}
 
 instance Yaml.FromYAML ConfigFile where
   parseYAML = Yaml.withMap "ConfigFile" $ \m -> do
@@ -67,6 +73,7 @@
     trustedRegistries <- m .:? "trustedRegistries"
     labelSchemaConfig <- m .:? "label-schema"
     strictLabelSchema <- m .:? "strict-labels"
+    failureThreshold <- m .:? "failure-threshold"
     return ConfigFile {..}
 
 -- | If both the ignoreRules and rulesConfig properties of Lint options are empty
@@ -77,19 +84,10 @@
 applyConfig maybeConfig o
   | not (Prelude.null (Lint.ignoreRules o)) && Lint.rulesConfig o /= mempty = return (Right o)
   | otherwise = do
-    theConfig <-
-      case maybeConfig of
-        Nothing -> findConfig
-        c -> return c
-    case theConfig of
+    case maybeConfig of
       Nothing -> return (Right o)
       Just config -> parseAndApply config
   where
-    findConfig = do
-      localConfigFile <- (</> ".hadolint.yaml") <$> getCurrentDirectory
-      configFile <- getXdgDirectory XdgConfig "hadolint.yaml"
-      listToMaybe <$> filterM doesFileExist [localConfigFile, configFile]
-
     parseAndApply :: FilePath -> IO (Either String Lint.LintOptions)
     parseAndApply configFile = do
       contents <- Bytes.readFile configFile
@@ -106,6 +104,7 @@
         overrideInfo <- overrideInfoRules <|> Just mempty
         overrideStyle <- overrideStyleRules <|> Just mempty
         overrideIgnored <- ignoredRules <|> Just mempty
+        overrideThreshold <- failureThreshold <|> Just mempty
 
         trusted <- Set.fromList . coerce <$> (trustedRegistries <|> Just mempty)
         schema <- labelSchemaConfig <|> Just mempty
@@ -125,7 +124,8 @@
                   { Process.allowedRegistries = Process.allowedRegistries rulesConfig `ifNull` trusted,
                     Process.labelSchema = Process.labelSchema rulesConfig `ifNull` schema,
                     Process.strictLabels = Process.strictLabels rulesConfig || strictLabels
-                  }
+                  },
+            Lint.failThreshold = Lint.failThreshold o <> overrideThreshold
             }
 
     ifNull value override = if null value then override else value
@@ -151,3 +151,20 @@
           "",
           err
         ]
+
+-- | Gets the configuration file which Hadolint uses
+getConfig :: Maybe FilePath -> IO (Maybe FilePath)
+getConfig maybeConfig =
+  case maybeConfig of
+    Nothing -> findConfig
+    _ -> return maybeConfig
+  where
+    findConfig :: IO (Maybe FilePath)
+    findConfig = do
+      localConfigFiles <- traverse
+                            (\filePath -> (</> filePath) <$> getCurrentDirectory)
+                            (fmap ("."++) acceptedConfigs)
+      configFiles <- traverse (getXdgDirectory XdgConfig) acceptedConfigs
+      listToMaybe <$> filterM doesFileExist (localConfigFiles ++ configFiles)
+      where
+        acceptedConfigs = ["hadolint.yaml", "hadolint.yml"]
diff --git a/src/Hadolint/Lint.hs b/src/Hadolint/Lint.hs
--- a/src/Hadolint/Lint.hs
+++ b/src/Hadolint/Lint.hs
@@ -24,13 +24,13 @@
 import Language.Docker.Parser (DockerfileError, Error)
 import Language.Docker.Syntax (Dockerfile)
 
-type ErrorRule = Text
+type ErrorRule = Hadolint.Rule.RuleCode
 
-type WarningRule = Text
+type WarningRule = Hadolint.Rule.RuleCode
 
-type InfoRule = Text
+type InfoRule = Hadolint.Rule.RuleCode
 
-type StyleRule = Text
+type StyleRule = Hadolint.Rule.RuleCode
 
 type IgnoreRule = Hadolint.Rule.RuleCode
 
@@ -42,12 +42,13 @@
     infoRules :: [InfoRule],
     styleRules :: [StyleRule],
     ignoreRules :: [IgnoreRule],
-    rulesConfig :: Hadolint.Process.RulesConfig
+    rulesConfig :: Hadolint.Process.RulesConfig,
+    failThreshold :: Hadolint.Rule.DLSeverity
   }
   deriving (Show)
 
 instance Semigroup LintOptions where
-  LintOptions a1 a2 a3 a4 a5 a6 <> LintOptions b1 b2 b3 b4 b5 b6 =
+  LintOptions a1 a2 a3 a4 a5 a6 a7 <> LintOptions b1 b2 b3 b4 b5 b6 b7 =
     LintOptions
       (a1 <> b1)
       (a2 <> b2)
@@ -55,9 +56,10 @@
       (a4 <> b4)
       (a5 <> b5)
       (a6 <> b6)
+      (a7 <> b7)
 
 instance Monoid LintOptions where
-  mempty = LintOptions mempty mempty mempty mempty mempty mempty
+  mempty = LintOptions mempty mempty mempty mempty mempty mempty mempty
 
 -- | Performs the process of parsing the dockerfile and analyzing it with all the applicable
 -- rules, depending on the list of ignored rules.
@@ -99,10 +101,10 @@
 fixSeverity LintOptions {..} = Seq.filter ignoredRules . Seq.mapWithIndex (const correctSeverity)
   where
     correctSeverity =
-      makeSeverity Hadolint.Rule.DLErrorC (fmap Hadolint.Rule.RuleCode errorRules)
-        . makeSeverity Hadolint.Rule.DLWarningC (fmap Hadolint.Rule.RuleCode warningRules)
-        . makeSeverity Hadolint.Rule.DLInfoC (fmap Hadolint.Rule.RuleCode infoRules)
-        . makeSeverity Hadolint.Rule.DLStyleC (fmap Hadolint.Rule.RuleCode styleRules)
+      makeSeverity Hadolint.Rule.DLErrorC errorRules
+        . makeSeverity Hadolint.Rule.DLWarningC warningRules
+        . makeSeverity Hadolint.Rule.DLInfoC infoRules
+        . makeSeverity Hadolint.Rule.DLStyleC styleRules
 
     ignoredRules = ignoreFilter ignoreRules
 
diff --git a/src/Hadolint/Rule.hs b/src/Hadolint/Rule.hs
--- a/src/Hadolint/Rule.hs
+++ b/src/Hadolint/Rule.hs
@@ -21,7 +21,30 @@
   | DLInfoC
   | DLStyleC
   | DLIgnoreC
-  deriving (Show, Eq, Ord, Generic, NFData)
+  deriving (Show, Read, Eq, Ord, Generic, NFData)
+
+instance Yaml.FromYAML DLSeverity where
+  parseYAML = withSeverity pure
+
+withSeverity :: (DLSeverity -> Yaml.Parser a) -> Yaml.Node Yaml.Pos -> Yaml.Parser a
+withSeverity f v@(Yaml.Scalar _ (Yaml.SStr b)) =
+  case Hadolint.Rule.readSeverity b of
+    Right s -> f s
+    Left _ -> Yaml.typeMismatch "severity" v
+withSeverity _ v = Yaml.typeMismatch "severity" v
+
+readSeverity :: Text.Text -> Either Text.Text DLSeverity
+readSeverity "error" = Right DLErrorC
+readSeverity "warning" = Right DLWarningC
+readSeverity "info" = Right DLInfoC
+readSeverity "style" = Right DLStyleC
+readSeverity "ignore" = Right DLIgnoreC
+readSeverity "none" = Right DLIgnoreC
+readSeverity t = Left ("Invalid severity: " <> t)
+
+instance Semigroup DLSeverity where s1 <> s2 = min s1 s2
+
+instance Monoid DLSeverity where mempty = DLIgnoreC
 
 newtype RuleCode = RuleCode {unRuleCode :: Text.Text}
   deriving (Show, Eq, Ord)
diff --git a/src/Hadolint/Rule/DL3060.hs b/src/Hadolint/Rule/DL3060.hs
--- a/src/Hadolint/Rule/DL3060.hs
+++ b/src/Hadolint/Rule/DL3060.hs
@@ -1,27 +1,74 @@
 module Hadolint.Rule.DL3060 (rule) where
 
+import qualified Data.Map.Strict as Map
+import qualified Data.Text as Text
 import Hadolint.Rule
 import qualified Hadolint.Shell as Shell
 import Language.Docker.Syntax
 
 
+data Acc
+  = Acc
+      { current :: BaseImage,
+        active :: Map.Map Text.Text Linenumber,
+        inactive :: Map.Map Linenumber BaseImage
+      }
+  | Empty
+  deriving (Show)
+
 rule :: Rule Shell.ParsedShell
-rule = simpleRule code severity message check
+rule = veryCustomRule check (emptyState Empty) markFailures
   where
     code = "DL3060"
     severity = DLInfoC
     message = "`yarn cache clean` missing after `yarn install` was run."
 
-    check (Run (RunArgs args _)) =
-      foldArguments (Shell.noCommands yarnInstall) args
-        || ( foldArguments (Shell.anyCommands yarnInstall) args
-              && foldArguments (Shell.anyCommands yarnCacheClean) args
-           )
-    check _ = True
+    check line st (From from) =
+      st |> modify (rememberStage line from)
+    check line st (Run (RunArgs args _))
+      | foldArguments (Shell.anyCommands yarnInstall) args
+          && foldArguments (Shell.noCommands yarnCacheClean) args =
+        st |> modify (rememberLine line)
+      | otherwise = st
+    check _ st _ = st
+
+    -- Produce failures from the final state Acc
+    markFailures :: State Acc -> Failures
+    markFailures (State fails Empty) = fails
+    markFailures (State _ Acc {..}) = inactive |> Map.foldMapWithKey mapFail
+      where
+        mapFail line from
+          | from == current = pure CheckFailure {..}
+          | BaseImage {alias = Just (ImageAlias als)} <- from,
+            Just _ <- Map.lookup als active = pure CheckFailure {..}
+          | otherwise = mempty
 {-# INLINEABLE rule #-}
 
+rememberStage :: Linenumber -> BaseImage -> Acc -> Acc
+rememberStage line stage@BaseImage {image = Image _ als} Empty =
+  Acc stage (Map.singleton als line) Map.empty
+rememberStage line stage@BaseImage {image = Image _ als} (Acc _ stages o) =
+  Acc stage (Map.insert als line stages) o
+
+rememberLine :: Linenumber -> Acc -> Acc
+rememberLine line Empty = Acc scratch mempty (Map.singleton line scratch)
+rememberLine line (Acc from stages o) = Acc from stages (Map.insert line from o)
+
 yarnInstall :: Shell.Command -> Bool
 yarnInstall = Shell.cmdHasArgs "yarn" ["install"]
 
 yarnCacheClean :: Shell.Command -> Bool
 yarnCacheClean = Shell.cmdHasArgs "yarn" ["cache", "clean"]
+
+-- | This is needed as placeholder when no FROM statement has yet been
+-- envountered.
+scratch :: BaseImage
+scratch =
+  ( BaseImage
+      { image = "scratch",
+        tag = Nothing,
+        digest = Nothing,
+        alias = Nothing,
+        platform = Nothing
+      }
+  )
diff --git a/test/ConfigSpec.hs b/test/ConfigSpec.hs
--- a/test/ConfigSpec.hs
+++ b/test/ConfigSpec.hs
@@ -20,7 +20,7 @@
               "    - SC1010"
             ]
           override = Just (OverrideConfig (Just ["DL3000", "SC1010"]) Nothing Nothing Nothing)
-          expected = ConfigFile override Nothing Nothing Nothing Nothing
+          expected = ConfigFile override Nothing Nothing Nothing Nothing Nothing
        in assertConfig expected (Bytes.unlines configFile)
 
     it "Parses config with only warning severities" $
@@ -31,7 +31,7 @@
               "    - SC1010"
             ]
           override = Just (OverrideConfig Nothing (Just ["DL3000", "SC1010"]) Nothing Nothing)
-          expected = ConfigFile override Nothing Nothing Nothing Nothing
+          expected = ConfigFile override Nothing Nothing Nothing Nothing Nothing
        in assertConfig expected (Bytes.unlines configFile)
 
     it "Parses config with only info severities" $
@@ -42,7 +42,7 @@
               "    - SC1010"
             ]
           override = Just (OverrideConfig Nothing Nothing (Just ["DL3000", "SC1010"]) Nothing)
-          expected = ConfigFile override Nothing Nothing Nothing Nothing
+          expected = ConfigFile override Nothing Nothing Nothing Nothing Nothing
        in assertConfig expected (Bytes.unlines configFile)
 
     it "Parses config with only style severities" $
@@ -53,7 +53,7 @@
               "    - SC1010"
             ]
           override = Just (OverrideConfig Nothing Nothing Nothing (Just ["DL3000", "SC1010"]))
-          expected = ConfigFile override Nothing Nothing Nothing Nothing
+          expected = ConfigFile override Nothing Nothing Nothing Nothing Nothing
        in assertConfig expected (Bytes.unlines configFile)
 
     it "Parses config with only ignores" $
@@ -62,7 +62,7 @@
               "- DL3000",
               "- SC1010"
             ]
-          expected = ConfigFile Nothing (Just ["DL3000", "SC1010"]) Nothing Nothing Nothing
+          expected = ConfigFile Nothing (Just ["DL3000", "SC1010"]) Nothing Nothing Nothing Nothing
        in assertConfig expected (Bytes.unlines configFile)
 
     it "Parses config with only trustedRegistries" $
@@ -71,7 +71,7 @@
               "- hub.docker.com",
               "- my.shady.xyz"
             ]
-          expected = ConfigFile Nothing Nothing (Just ["hub.docker.com", "my.shady.xyz"]) Nothing Nothing
+          expected = ConfigFile Nothing Nothing (Just ["hub.docker.com", "my.shady.xyz"]) Nothing Nothing Nothing
        in assertConfig expected (Bytes.unlines configFile)
 
     it "Parses config with only label-schema" $
@@ -80,14 +80,19 @@
               "  author: text",
               "  url: url"
             ]
-          expected = ConfigFile Nothing Nothing Nothing (Just (fromList [("author", Rule.RawText), ("url", Rule.Url)])) Nothing
+          expected = ConfigFile Nothing Nothing Nothing (Just (fromList [("author", Rule.RawText), ("url", Rule.Url)])) Nothing Nothing
        in assertConfig expected (Bytes.unlines configFile)
 
     it "Parses config with only label-schema" $
       let configFile = [ "strict-labels: true" ]
-          expected = ConfigFile Nothing Nothing Nothing Nothing (Just True)
+          expected = ConfigFile Nothing Nothing Nothing Nothing (Just True) Nothing
        in assertConfig expected (Bytes.unlines configFile)
 
+    it "Parses config with failure-threshold" $
+      let configFile = [ "failure-threshold: error" ]
+          expected = ConfigFile Nothing Nothing Nothing Nothing Nothing (Just Rule.DLErrorC)
+       in assertConfig expected (Bytes.unlines configFile)
+
     it "Parses full file" $
       let configFile =
             [ "override:",
@@ -109,11 +114,13 @@
               "strict-labels: false",
               "label-schema:",
               "  author: text",
-              "  url: url"
+              "  url: url",
+              "",
+              "failure-threshold: style"
             ]
           override = Just (OverrideConfig (Just ["DL3001"]) (Just ["DL3003"]) (Just ["DL3002"]) (Just ["DL3004"]))
           labelschema = Just (fromList [("author", Rule.RawText), ("url", Rule.Url)])
-          expected = ConfigFile override (Just ["DL3000"]) (Just ["hub.docker.com"]) labelschema (Just False)
+          expected = ConfigFile override (Just ["DL3000"]) (Just ["hub.docker.com"]) labelschema (Just False) (Just Rule.DLStyleC)
        in assertConfig expected (Bytes.unlines configFile)
 
 assertConfig :: HasCallStack => ConfigFile -> Bytes.ByteString -> Assertion
diff --git a/test/DL3060.hs b/test/DL3060.hs
--- a/test/DL3060.hs
+++ b/test/DL3060.hs
@@ -1,5 +1,6 @@
 module DL3060 (tests) where
 
+import qualified Data.Text as Text
 import Helpers
 import Test.Hspec
 
@@ -17,3 +18,51 @@
     it "ok with cache clean" $ do
       ruleCatchesNot "DL3060" "RUN yarn install bar && yarn cache clean"
       onBuildRuleCatchesNot "DL3060" "RUN yarn install bar && yarn cache clean"
+
+    it "not ok when yarn install is in last stage w/o yarn clean" $
+      let dockerFile =
+            Text.unlines
+              [ "FROM node:lts-alpine as foo",
+                "RUN hey!",
+                "FROM scratch",
+                "RUN yarn install"
+              ]
+       in do
+            ruleCatches "DL3060" dockerFile
+            onBuildRuleCatches "DL3060" dockerFile
+
+    it "not ok when inheriting from stage with yarn install w/o yarn clean" $
+      let dockerFile =
+            Text.unlines
+              [ "FROM node:lts-alpine as foo",
+                "RUN yarn install",
+                "FROM foo",
+                "RUN hey!"
+              ]
+       in do
+            ruleCatches "DL3060" dockerFile
+            onBuildRuleCatches "DL3060" dockerFile
+
+    it "ok when inheriting from stage with yarn cache clear" $
+      let dockerFile =
+            Text.unlines
+              [ "FROM node:lts-alpine as foo",
+                "RUN yarn install && yarn cache clean",
+                "FROM foo",
+                "RUN hey!"
+              ]
+       in do
+            ruleCatchesNot "DL3060" dockerFile
+            onBuildRuleCatchesNot "DL3060" dockerFile
+
+    it "ok when omitting yarn cache clean in stage that is not reused later" $
+      let dockerFile =
+            Text.unlines
+              [ "FROM node:lts-alpine as foo",
+                "RUN yarn install foo",
+                "FROM scratch",
+                "RUN hey!"
+              ]
+       in do
+            ruleCatchesNot "DL3060" dockerFile
+            onBuildRuleCatches "DL3060" dockerFile
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -60,6 +60,7 @@
 import qualified DL3057
 import qualified DL3058
 import qualified DL3059
+import qualified DL3060
 import qualified DL4001
 import qualified DL4003
 import qualified DL4004
@@ -84,7 +85,7 @@
             expectedMsg =
               "<string>:1:1 unexpected 'F' expecting '#', ADD, ARG, CMD, COPY, ENTRYPOINT, "
                 <> "ENV, EXPOSE, FROM, HEALTHCHECK, LABEL, MAINTAINER, ONBUILD, RUN, SHELL, STOPSIGNAL, "
-                <> "USER, VOLUME, WORKDIR, or end of input "
+                <> "USER, VOLUME, WORKDIR, a pragma, end of input, or whitespaces "
         case ast of
           Left err -> assertEqual "Unexpected error msg" expectedMsg (formatError err)
           Right _ -> assertFailure "AST should fail parsing"
@@ -230,6 +231,7 @@
     DL3057.tests
     DL3058.tests
     DL3059.tests
+    DL3060.tests
     DL4001.tests
     DL4003.tests
     DL4004.tests
