       if data?
         @sKey = data.transaction.session_key
         @txID = data.transaction.txid
-        console.log "Updating transaction: ", @sKey, @txID
+        #console.log "Updating transaction: ", @sKey, @txID
 
     @poll = (url, cb, timeout=@config?.timeout?.long) =>
       rePoll = (data) =>


    @wsTemp = ko.observableArray()
    @wsItems = ko.computed(=>
      @wsTemp()?[0]?.children ? []).extend throttle: 200 # Coalesce node changes

    @wsPlans = ko.observableArray()
    @wsKeys = {}

      root = {}

      parseChildren = (node) ->
        node.agents = (v for k,v of node?.children when "agent" in v.facts.backends)
        node.containers = (v for k,v of node?.children  when "container" in v.facts.backends)

      # Index node list by ID, merging/updating if keyed was provided
      for node in data.nodes
        nid = node.id
        if keyed[nid]? # Updating existing node?
          pid = keyed[nid].facts?.parent_id # Grab current parent
          if pid? and pid isnt node.facts?.parent_id # If new parent is different
            delete keyed[pid].children[nid] # Remove node from old parent's children

        # Stub if missing
        node.actions ?= []
        node.status ?= "unknown"
        keyed[nid] = node # Add/update node

      # Step through IDs
      for id of keyed
        node = keyed[id]
        node.children ?= {}
        pid = node.facts?.parent_id
        if pid? # Has parent ID?
          pnode = keyed?[pid]
          if pnode? # Parent exists?
            pnode.children[id] = node # Add to parent's children
          else # We're an orphan (broken data or from previous merge)
            delete keyed[id] # No mercy for orphans!
        else if node.name is "workspace" # Mebbe root node?
          root = node # Point at it
        else # Invalid root node!
          delete keyed[id] # Pew Pew!

      for id of keyed
        parseChildren keyed[id]

      pin keyed if pin? # Update pin with keyed
      children: root # Return in format appropriate for mapping
