code: func (r *runner) doFailure(seed int64, chance float32) (stop bool, err error) {
  	failed := chance >= 1.0
  	if !failed {
  		logging.Fields{"chance": chance}.Infof(r.c, "failing with probability")
  		rndVal := rand.New(rand.NewSource(seed)).Float32()
  		failed = rndVal <= chance
  		logging.Fields{"rndVal": rndVal}.Infof(r.c, "failed")
  	} else {
  		logging.Infof(r.c, "failed (guaranteed)")
  	}
  
  	if !failed {
  		logging.Infof(r.c, "passed")
  		return
  	}
  
  	stop = true
  	_, err = r.dmc.FinishAttempt(r.c, &dm.FinishAttemptReq{
  		Auth: r.auth,
  		Data: executionResult(false, 0, time.Time{}),
  	})
  	if err != nil {
  		logging.WithError(err).Warningf(r.c, "got error on FinishAttempt")
  	}
  	return
  }
docs: // doFailure implements a jobsim task having some flakiness (e.g. it will
  // non-deterministically select to fail at this stage). If it fails, this will
  // cause the overall application-level Attempt Result to indicate failure to any
  // other Attempts which depend on this one.
  //
  // This is analogous to a recipe running a flaky test and then setting its
  // result to be failure. As far as DM is concerned, the recipe ran to completion
  // (e.g. FINISHED). Other recipes may decide to take some action at this stage
  // (e.g. issue new Attempts of this same Quest).