anchor.diff:              callback completeCount
               return! chooseState(newState) }
   
  -        and setWorking (worker, reply, state : RunningState<'TGroup, 'TItem>) =
  +         and setWorking (worker, reply, state : RunningState<'TGroup, 'TItem>) =
               let (group, newQueue) = state.AvailableWorkQueue |> Queue.uncons
               let items = state.CurrentItems.Items.[group]
               async {
  
positive.code:     WaitingItems : GroupedItems<'TGroup, 'TItem>
  }
  
  type QueueMode =
      | Empty
      | NotFullWorkAvailable
      | NotFullNoWorkAvailable
      | FullWorkAvailable
      | FullNoWorkAvailable
  
  type GroupingBoundedQueue<'TGroup, 'TItem, 'TResult when 'TGroup : comparison>(maxItems) =
      let empty = { AvailableWorkQueue = Queue.empty; RunningGroups = Set.empty; CurrentItems = { Items = Map.empty; ItemCount = 0}; WaitingItems = { Items = Map.empty; ItemCount = 0} }
  
      let getStateSummary runningState =
          let itemCount = runningState.CurrentItems.ItemCount + runningState.WaitingItems.ItemCount
          let workAvailable = not runningState.AvailableWorkQueue.IsEmpty
          match itemCount with
          | 0 -> Empty
          | count when count < maxItems -> 
              if(workAvailable) then
                  NotFullWorkAvailable
              else
                  NotFullNoWorkAvailable
          | _ ->
              if(workAvailable) then
                  FullWorkAvailable
              else
                  FullNoWorkAvailable
  
      let agentDef callback = Agent.Start(fun agent ->
  
          let rec emptyQueue(state) =
              agent.Scan(fun msg -> 
               match msg with
               | AsyncAdd(group, value, reply) -> Some(enqueue(group, value, reply, state))
               | _ -> None) 
  
           and notFullWorkAvailable(runningState) = async {
              let! msg = agent.Receive()
              match msg with 
              | AsyncAdd(group, value, reply) -> return! enqueue(group, value, reply, runningState)
              | AsyncComplete(work, reply) -> return! setWorking(work, reply, runningState)
              | WorkComplete(group) -> return! workComplete(group, runningState) }
  
           and notFullNoWorkAvailable(runningState) = 
              agent.Scan(fun msg -> 
               match msg with
               | AsyncAdd(group, value, reply) -> Some(enqueue(group, value, reply, runningState))
               | WorkComplete(group) -> Some(workComplete(group, runningState))
               | _ -> None)
  
          and fullWorkAvailable(runningState) = 
              agent.Scan(fun msg -> 
               match msg with
               | AsyncComplete(work, reply) -> Some(setWorking(work, reply, runningState))
               | WorkComplete(group) -> Some(workComplete(group, runningState))
               | _ -> None)
  
          and fullNoWorkAvailable(runningState) = 
              agent.Scan(fun msg -> 
               match msg with
               | WorkComplete(group) -> Some(workComplete(group, runningState))
               | _ -> None)
  
  
negative.code:             chooseState(newState)
  
          and chooseState(runningState) = 
              if(runningState.AvailableWorkQueue.IsEmpty) then
                  noWorkAvailable(runningState)
              else
                  workAvailable(runningState)
  
          noWorkAvailable(empty)
      )
  
      let rec boundedWorkQueue = new BoundedWorkQueue<('TGroup * 'TItem)>(maxItems, postWorkToAgent)
  