function groupBails (rules) {
  const groups = []
  const bailIndex = rules.findIndex(([,, rule]) => rule.toLowerCase() === 'bail')
  const optionalIndex = rules.findIndex(([,, rule]) => rule.toLowerCase() === 'optional')
  if (optionalIndex >= 0) {
    const rule = rules.splice(optionalIndex, 1)
    groups.push(Object.defineProperty(rule, 'bail', { value: true }))
  }
  if (bailIndex >= 0) {
    // Get all the rules until the first bail rule (dont include the bail)
    const preBail = rules.splice(0, bailIndex + 1).slice(0, -1)
    // Rules before the `bail` rule are non-bailing
    preBail.length && groups.push(preBail)
    // All remaining rules are bailing rule groups
    rules.map(rule => groups.push(Object.defineProperty([rule], 'bail', { value: true })))
  } else {
    groups.push(rules)
  }

  return groups.reduce((groups, group) => {
    // Recursively split rules into groups based on the modifiers.
    const splitByMod = (group, bailGroup = false) => {
      if (group.length < 2) {
        return Object.defineProperty([group], 'bail', { value: bailGroup })
      }
      const splits = []
      const modIndex = group.findIndex(([,,, modifier]) => modifier === '^')
      if (modIndex >= 0) {
        const preMod = group.splice(0, modIndex)
        // rules before the modifier are non-bailing rules.
        preMod.length && splits.push(...splitByMod(preMod, bailGroup))
        splits.push(Object.defineProperty([group.shift()], 'bail', { value: true }))
        // rules after the modifier are non-bailing rules.
        group.length && splits.push(...splitByMod(group, bailGroup))
      } else {
        splits.push(group)
      }
      return splits
    }
    return groups.concat(splitByMod(group))
  }, [])
}
Given an array of rules, group them by bail signals. For example for this:
bail|required|min:10|max:20
we would expect:
[[required], [min], [max]]
because any sub-array failure would cause a shutdown. While
^required|min:10|max:10
would return:
[[required], [min, max]]
and no bailing would produce:
[[required, min, max]]
@param {array} rules