anchor.diff:            | false -> raiseError ctx (sprintf "Neither rule nor file is found for '%s'" (getFullname target)) ""
   
       /// Executes several artifacts in parallel
  -    and private exec ctx = Seq.ofList >> Seq.map (execOne ctx) >> Async.Parallel
  -
  -    /// Executes and awaits specified artifacts
  -    /// Returns ExecStatus indicating is any target was built (files are considered untouched)
  -    and needTarget targets =
  -      action {
  -        let! ctx = getCtx()
  -        ctx.Throttler.Release() |> ignore
  -        let! execStatuses = targets |> exec ctx
  -        do! ctx.Throttler.WaitAsync(-1) |> Async.AwaitTask |> Async.Ignore
  -
  -        let dependencies = execStatuses |> Array.map snd
  -        let anyUpdated = execStatuses |> Array.map fst |> Array.exists ((=) ExecStatus.Succeed)
  -
  -        let! result = getResult()
  -        do! setResult {result with Depends = result.Depends @ Array.toList dependencies}
  -
  -        // TODO how to check if any file was changed and what does result mean?
  -        return if anyUpdated then ExecStatus.Succeed else ExecStatus.Skipped
  -      }
  -    and needTarget1 ctx targets =
  -      // TODO get rid off of above method
  -      // return list of statuses
  +    and private execMany ctx = Seq.ofList >> Seq.map (execOne ctx) >> Async.Parallel
  +
  +    /// Gets the status of dependency artifacts (obtained from 'need' calls)
  +    and execNeed ctx targets : Async<ExecStatus * Dependency list> =
         async {
           ctx.Throttler.Release() |> ignore
  -        let! execStatuses = targets |> exec ctx
  +        let! statuses = targets |> execMany ctx
           do! ctx.Throttler.WaitAsync(-1) |> Async.AwaitTask |> Async.Ignore
   
  -        let dependencies = execStatuses |> Array.map snd
  -        let anyUpdated = execStatuses |> Array.map fst |> Array.exists ((=) ExecStatus.Succeed)
  -
  -        // TODO how to check if any file was changed and what does result mean?
  -        return if anyUpdated then ExecStatus.Succeed else ExecStatus.Skipped
  +        let dependencies = statuses |> Array.map snd |> List.ofArray in
  +        let status = match statuses |> Array.exists (fst >> (=) ExecStatus.Succeed) with
  +                      | true -> ExecStatus.Succeed
  +                      | _ -> ExecStatus.Skipped
  +
  +        return status,dependencies
         }
   
       // phony actions are detected by their name so if there's "clean" phony and file "clean" in `need` list if will choose first
  
positive.code:       do reportError ctx error details
        raise (XakeException(sprintf "Script failed (error code: %A)\n%A" error details))
  
      // executes single artifact
      let rec private execOne ctx target =
  
        /// Gets true if rebuild is required
        let needRebuild (tgt:Target) result =
  
          let reason tgt msg file = function
            | true ->
              do ctx.Logger.Log Info "Rebuild %A: %s, src '%s'" (getShortname tgt) msg file
              true
            | _ -> false
  
          // check simple rules (all but ArtifactDep) synchronously
          // request "dependencies"
          let isOutdated (tgt:Target) = function
            | File (a:Artifact, wrtime) ->
                not(a.Exists && abs((a.LastWriteTime - wrtime).TotalMilliseconds) < TimeCompareToleranceMs)
                |> reason tgt "removed or changed file" a.Name
  
            | ArtifactDep (FileTarget file) ->
                not file.Exists |> reason tgt "target doesn't exist" file.Name
    //        | ArtifactDep _ ->
    //            let lastBuildResult = (fun ch -> GetResult(target, ch)) |> ctx.Db.PostAndReply
    //            lastBuildResult |> isOutdatedResult target |> reason tgt "dependency changed" "many"
  
            | EnvVar (name,value) ->
                let newValue = System.Environment.GetEnvironmentVariable(name) in
                value <> newValue
  
            | Var (name,value) -> false
            | AlwaysRerun -> true |> reason tgt "alwaysRerun" "none"
  
          let result, reason, (deps: Target list) =
            match result with
            | Some {BuildResult.Depends = []} ->
                true, "No dependencies", []
  
            | Some {BuildResult.Result = FileTarget file} when not file.Exists ->
                true, sprintf "target not found: '%s'" file.Name, []
  
            | Some result ->
                let artifactDeps, immediateDeps = result.Depends |> List.partition (function |ArtifactDep (FileTarget file) when file.Exists -> true | _ -> false)
  
                let outdated =  immediateDeps |> List.exists (isOutdated result.Result) in  // TODO pass reason
                let targets = artifactDeps |> List.map (function |ArtifactDep dep -> dep)
                in
                outdated, "", targets
                // result.Depends |> List.exists (isOutdated result.Result), ""
  
            | _ -> true, "reason unknown (new file&)", []
  
          if result = true then
            do ctx.Logger.Log Info "Rebuild %A: %s" (getShortname tgt) reason
            async {return true}
          else
            async {
              let! status = needTarget1 ctx deps
              return status = ExecStatus.Succeed
            }
  
        let run action chnl =
          Run(target,
            async {
              let! lastBuild = (fun ch -> GetResult(target, ch)) |> ctx.Db.PostAndAsyncReply
  
              let! doRebuild = needRebuild target lastBuild
  
              if doRebuild then
                do ctx.Logger.Log Command "Started %s" (getShortname target)
  
negative.code:   /// Executes and awaits specified artifacts
    let needFileset fileset =
        action {
          let! ctx = getCtx()
          let targets = fileset |> (toFileList ctx.Options.ProjectRoot >> List.map (fun f -> new Artifact (f.FullName) |> FileTarget))
          let! _,deps = targets |> Impl.execNeed ctx
  
          let! result = getResult()
          do! setResult {result with Depends = result.Depends @ deps}
       }
  
    /// Executes and awaits specified artifacts
    let need targets =
        action {
          let! ctx = getCtx()
          let t' = targets |> (List.map (Impl.makeTarget ctx))
          let! _,deps = t' |> Impl.execNeed ctx
  
          let! result = getResult()
          do! setResult {result with Depends = result.Depends @ deps}
        }
  
    /// Instructs Xake to rebuild the target evem if dependencies are not changed
  