diff --git a/README.md b/README.md
index 0d9891a3ce5272552f503d607b9cf104babb7281..bccdae1574247a5f35fa100f65a61db6ef1d86b6 100644
--- a/README.md
+++ b/README.md
@@ -134,7 +134,7 @@ There's some UI leftovers in the view.
  - the link is a hot mess, unwritten, you have to do this to start serialization
  - the view is still itchy
   - force layout ... zoom to extents always (or if checked state?)
-   - have checked state, just write the zoomExtents function 
+   - have checked state, just write the zoomExtents function
   - force layout ... no overlapping
   - force layout ... use links as forces
   - force layout ... push relationships between constituents
@@ -213,3 +213,19 @@ Here's a list of things that I suspect will eventually roll themselves into bugs
  - escape key to leave menu (/ keys on dom ? /on new right-click etc)
  - on zoom, check if element is view or not,
  - if not view (is block) then look for event parent position, not event
+
+# ~scraaaatch -~ we have to re-write input / output / state items as genuine lists
+
+ - load bootstrap program, see view of two
+  - messages need 2 be mobile, and we need 2 see them
+
+on by-index or by-object
+ (1) rewriting js as by-index might be a pita, most messages are by-string now ... which keys really nicely
+ (2) we *could* do this by-index, and then messages might be routed-all-the-way-down ...
+ (3) I think that by-index is worth it if only for the likeness to cpp implementation
+
+where work needs to happen for by-index
+ - manager transport (?) ok (?) bugpatrol
+ - manager.statechange (?) ok (?)
+ - putdef (?) apparently works either way ?
+ - addlink, find by name in array (?) ok feels good (?) 
diff --git a/bootstrap.js b/bootstrap.js
index fbd2899eb378ff3c5fe79bd100c9549f829c3a0b..c0ee09f41ef4712ab8963b8dcda70dec2b16986f 100644
--- a/bootstrap.js
+++ b/bootstrap.js
@@ -45,11 +45,13 @@ window.onload = () => {
         // NROL.describeRunningProgram()
         bootloop()
         // and then we can load this program
+        /*
         NROL.addProgram('mvnv').then((newHunks) => {
             // auto added to view (should be)
         }).catch((err) => {
             console.log('ERR on opening bootstrap program:', err)
         })
+        */
     }).catch((err) => {
         console.log(err)
     })
diff --git a/hunks/hunks.js b/hunks/hunks.js
index 7efcb6ec6bccbd215be152d89b9c39089fe5e905..b930d6a378a5e115b4af9aa8803956c920c3c382 100644
--- a/hunks/hunks.js
+++ b/hunks/hunks.js
@@ -16,7 +16,7 @@ function Hunkify(hunk, name) {
     }
   }
 
-  // input, output, and state: ay balls, here we go 
+  // input, output, and state: ay balls, here we go
   hunk.inputs = new Array()
   hunk.outputs = new Array()
   hunk.state = new Array()
@@ -48,7 +48,7 @@ function Input(type, name) {
   this.get = () => {
     // used internal to hunk to pull data from link
     if (this.io) {
-      // TODO: BIG: deep copy here
+      // TODO: BIG: deep copy here, not this bs bs bs WIP WIP WIP WIP4EVER
       let dc = JSON.parse(JSON.stringify(this.data))
       this.data = null
       this.io = false
diff --git a/hunks/input/string.js b/hunks/input/string.js
index 5127bdbff94fdb0b4a7e0402f9e996e095b51a17..4272342fb498db1a2d8413168d3715e86e7d9996 100644
--- a/hunks/input/string.js
+++ b/hunks/input/string.js
@@ -11,8 +11,11 @@ function Strang() {
 
     this.description = 'click pow pow'
 
-    this.inputs.thru = new Input('any', 'thru')
-    this.outputs.string = new Output('string', 'string')
+    let thruput = new Input('any', 'thru')
+    this.inputs.push(thruput)
+
+    let stringOutput = new Output('string', 'string')
+    this.outputs.push(stringOutput)
 
     // this.state.prefix = new State('string', 'prefix', 'LOG:')
     // this.state.onchange = new State('boolean', 'onchange', true)
@@ -20,11 +23,11 @@ function Strang() {
     this.dom = {}
 
     this.init = () => {
-        // manager calls this once 
+        // manager calls this once
         // it is loaded and state is updated (from program)
         this.log('hello String')
         this.dom = $('<div>').get(0)
-        // au manuel 
+        // au manuel
         this.dom.style.marginTop = '40px'
         let strContainer = $('<div>').addClass('cfcont').appendTo($(this.dom))
         let strinput = $('<input/>').attr({type: 'text', id: 'txtin'}).addClass('txtinput').appendTo($(strContainer)).get(0)
@@ -33,18 +36,18 @@ function Strang() {
         $(this.dom).append(contact)
         contact.addEventListener('click', (evt) => {
             console.log('str click')
-            this.outputs.string.put(strinput.value)
+            stringOutput.put(strinput.value)
         })
     }
 
     this.loop = () => {
         /*
-        if (this.inputs.thru.io && this.outputs.string.ie) {
-            // TODO decide about primitives and conversions 
-            this.outputs.string.put(JSON.stringify(this.inputs.thru.get()))
+        if (thruput.io && stringOutput.ie) {
+            // TODO decide about primitives and conversions
+            stringOutput.put(JSON.stringify(thruput.get()))
         }
         */
     }
 }
 
-export default Strang
\ No newline at end of file
+export default Strang
diff --git a/hunks/manager.js b/hunks/manager.js
index e1e90548394a7d984c0e880f769cf1752d7356b6..d89f3e12459177f50a1e12f4c36f9bbc01073540 100644
--- a/hunks/manager.js
+++ b/hunks/manager.js
@@ -21,7 +21,9 @@ function Manager() {
   let hunkCount = 0
   let hunks = new Array()
 
-  let verbose = false
+  // debug flags
+  let verbose = true
+  let msgverbose = true
 
   /* ---------------------------    ---------------------------- */
   /* -------------------- STD MGR INTERFACE -------------------- */
@@ -48,6 +50,8 @@ function Manager() {
   }
 
   let errmsg = (message) => {
+    // also log this for chrissake
+    console.log('ERRMSG', message)
     this.writemessage('error', message)
   }
 
@@ -78,6 +82,7 @@ function Manager() {
 
   this.sendHunkAsDef = (hunk) => {
     let def = writeDefinition(hunk)
+    if (msgverbose) this.log('msg: putdef', def)
     this.writemessage('putdef', def)
   }
 
@@ -97,7 +102,7 @@ function Manager() {
     }
 
     // add inputs
-    if (Object.keys(hunk.inputs).length > 0) {
+    if (hunk.inputs.length > 0) {
       for (let key in hunk.inputs) {
         let input = hunk.inputs[key]
         def.inputs[input.name] = {
@@ -108,7 +113,7 @@ function Manager() {
     }
 
     // add outputs
-    if (Object.keys(hunk.outputs).length > 0) {
+    if (hunk.outputs.length > 0) {
       for (let key in hunk.outputs) {
         let output = hunk.outputs[key]
         def.outputs[output.name] = {
@@ -129,7 +134,7 @@ function Manager() {
     }
 
     // add outputs
-    if (Object.keys(hunk.state).length > 0) {
+    if (hunk.state.length > 0) {
       for (let key in hunk.state) {
         let state = hunk.state[key]
         def.state[state.name] = {
@@ -221,11 +226,11 @@ function Manager() {
     }
 
     // now we update it's state if we have any of *that* to do
-    if(state !== undefined && state !== null){
-      for(let ro in state){
+    if (state !== undefined && state !== null) {
+      for (let ro in state) {
         // ro is the key
-        if(hunk.state[ro] !== undefined){
-          if(typeof hunk.state[ro].value == typeof state[ro]){
+        if (hunk.state[ro] !== undefined) {
+          if (typeof hunk.state[ro].value == typeof state[ro]) {
             hunk.state[ro].value = state[ro]
           } else {
             this.writemessage('error', 'problematic state content in program, not same type')
@@ -285,24 +290,34 @@ function Manager() {
     let inHunk = hunks.find((hunk) => {
       return hunk.id == inHunkId
     })
-    // console.log('found hunks', outHunk, inHunk)
+    // throw possible errs,
     if (outHunk === undefined) {
-      errmsg("MGR on ADDLINK: outHunk is undefined: " + outHunkId)
+      errmsg("MGR on ADDLINK: outHunk is undefined, on request for: " + outHunkId)
       return false
     }
     if (inHunk === undefined) {
-      errmsg("MGR on ADDLINK: inHunk is undefined: " + inHunkId)
+      errmsg("MGR on ADDLINK: inHunk is undefined, on request for: " + inHunkId)
       return false
     }
-    if (outHunk.outputs[outputName] === null || outHunk.outputs[outputName] === undefined) {
-      errmsg('MGR on ADDLINK: output is null or undefined. for hunk: ' + outHunk.id + " and output: " + outputName)
+
+    // find outputs, inputs
+    let otp = outHunk.outputs.find((op) => {
+      return op.name === outputName
+    })
+    let inp = inHunk.inputs.find((ip) => {
+      return ip.name === inputName
+    })
+    // throw errs,
+    if (otp === undefined) {
+      errmsg('MGR on ADDLINK: output is undefined. on request for hunk: ' + outHunkId + " and output: " + outputName)
       return false
-    } else if (inHunk.inputs[inputName] === null || inHunk.inputs[inputName] === undefined) {
+    } else if (inp === undefined) {
       errmsg('MGR on ADDLINK: input is null or undefined. for hunk: ' + inHunk.id + " and output: " + inputName)
       return false
     } else {
-      if(verbose) this.log(`hooking ${outHunk.id} to ${inHunk.id}`)
-      outHunk.outputs[outputName].attach(inHunk.inputs[inputName], inHunk.id)
+      if (verbose) this.log(`hooking ${outHunk.id}, ${otp.name} to ${inHunk.id}, ${inp.name}`)
+      otp.attach(inp, inHunk.id)
+      // should be verbatim, so
       this.writemessage('putlink', {
         outId: outHunkId,
         outName: outputName,
@@ -358,22 +373,20 @@ function Manager() {
   /* ---------------------------    ---------------------------- */
 
   this.stateChange = (hunkId, stateName, newValue) => {
+    // this is probably a good example of whomst to implement things-like-this
     return new Promise((resolve, reject) => {
-      this.log(`to change ${stateName} to ${newValue} in ${hunkId}`)
+      if(verbose) this.log(`to change ${stateName} to ${newValue} in ${hunkId}`)
       let theHunk = hunks.find((hunk) => {
         return hunk.id == hunkId
       })
-      if (theHunk !== undefined) {
-        let theState = theHunk.state[stateName]
-        if (theState !== null && theState !== undefined) {
-          theState.change(newValue)
-          resolve()
-        } else {
-          reject(new Error('@ statechange theState is undefined'))
-        }
-      } else {
-        reject(new Error('@ statechange theHunk is undefined'))
-      }
+      if(theHunk === undefined) reject(new Error('no hunk found for statechange'))
+      let theState = theHunk.state.find((st8) => {
+        return st8.name === stateName
+      })
+      if(theState === undefined) reject(new Error('no state found for statechange'))
+      // otherwise, do business
+      theState.change(newValue)
+      resolve()
     })
   }
 
@@ -393,7 +406,7 @@ function Manager() {
         if (obj.programname !== null && obj.programname !== undefined) {
           errmsg(`opening program with name: ${obj.programname}`)
           addHunkList(obj.hunks).then((newHunks) => {
-            if(verbose) this.log(`finished adding hunks from: ${obj.programname}, now links`)
+            if (verbose) this.log(`finished adding hunks from: ${obj.programname}, now links`)
             for (let lnk of obj.links) {
               if (this.addLink(lnk.outhunk, lnk.outname, lnk.inhunk, lnk.inname)) {
                 // success! continue
@@ -455,16 +468,13 @@ function Manager() {
     this.log(`manager hello, id is ${this.id}`)
   }
 
-  // flag,
-  let msgdebug = false
-
   this.loop = () => {
     // getting messages
     if (msgsin.io) {
       let msg = msgsin.get()
       let header = msg.header
       let content = msg.content
-      if(msgdebug) this.log(`gets msg ${header}`)
+      if (msgverbose) this.log(`gets msg ${header}`)
       switch (header) {
         case 'hello':
           let options = this.getHelloResponses()
@@ -504,7 +514,7 @@ function Manager() {
             this.log('added hunk with id', hunk.id)
           }).catch((err) => {
             this.log('ERR while adding hunk', err)
-            this.writemessage('error', 'ERR on adding hunk' + err)
+            this.writemessage('error', 'ERR on adding hunk: ' + err)
           })
           break
         case 'removehunk':
@@ -549,7 +559,7 @@ function Manager() {
       if (msgsout.ie) {
         if (debug) {
           let msg = this.outmsgbuffer.shift()
-          if (msgdebug) this.log(`msg out ${msg.header}`)
+          if (msgverbose) this.log(`buffer release msg type: ${msg.header}`)
           //console.log(msg.content)
           msgsout.put(msg)
         } else {
@@ -558,75 +568,60 @@ function Manager() {
       }
     } // end msgs output check
 
-    // do checks
-    if (hunks.length > 0) {
-      // STEP ONE: transport outputs (posted on last loop) to inputs
-      hunks.forEach((hunk) => {
-        for (let key of Object.keys(hunk.outputs)) {
-          let output = hunk.outputs[key]
-          if (output.connections.length > 0) {
-            // if we have connections
-            if (output.io) {
-              // and the output is occupied (having data)
-              if (!output.posted) {
-                // if it has not been posted to inputs (it's fresh)
-                // double check that all inputs are clear
-                let clear = true
-                for (let pair of output.connections) {
-                  if (pair.input.io) {
-                    clear = false
-                  }
-                }
-                // if all clear, move the output data to each input
-                if (clear) {
-                  for (let pair of output.connections) {
-                    // TODO: BIG copy per-input (within put function call)
-                    pair.input.put(output.data)
-                  }
-                  output.posted = true
-                } else {
-                  console.log('ERR: Output was put before inputs were clear')
+    hunks.forEach((hunk) => {
+      // begin transport, walk each output and push along
+      hunk.outputs.forEach((output) => {
+        if (output.connections.length > 0) {
+          // if we have connections
+          if (output.io) {
+            // and the output is occupied (having data)
+            if (!output.posted) {
+              // if it has not been posted to inputs (it's fresh)
+              // double check that all inputs are clear
+              let clear = true
+              for (let pair of output.connections) {
+                if (pair.input.io) {
+                  clear = false
                 }
-              } else {
-                // output has been posted, check if all clear
-                let clear = true
+              }
+              // if all clear, move the output data to each input
+              if (clear) {
                 for (let pair of output.connections) {
-                  if (pair.input.io) {
-                    clear = false
-                  }
+                  // TODO: BIG copy per-input (within put function call)
+                  pair.input.put(output.data)
                 }
-                if (clear) {
-                  output.clear()
+                output.posted = true
+              } else {
+                console.log('ERR: Output was put before inputs were clear')
+              }
+            } else {
+              // output has been posted, check if all clear
+              let clear = true
+              for (let pair of output.connections) {
+                if (pair.input.io) {
+                  clear = false
                 }
               }
-            } // end if-has-data
-          } else {
-            // and output with no connections is automatically cleared
-            // into the aether
-            if (output.io) {
-              output.clear()
+              if (clear) {
+                output.clear()
+              }
             }
+          } // end if-has-data
+        } else {
+          // and output with no connections is automatically cleared
+          // into the aether
+          if (output.io) {
+            output.clear()
           }
         }
-      }) // end connection passing loop
-      // STEP TWO: give each hunk some time to run
-      // the 0is us, let's not call its loop
-      for (let i = 1; i < hunks.length; i++) {
-        // TODO: watch for ordered calls ? if one emits ... another catches,
-        // we want cah-chunking ?
-        hunks[i].loop()
-      }
-    } // end if-have-hunks conditional
+      }) // end for each output
+    }) // end forEach((hunk)) for transport
 
-    /*
-    // need this at the bootloop, not here also
-    // setup to loop return
-    if (this.isBrowser) {
-        setTimeout(this.loop)
-    } else {
-        setImmediate(this.loop)
+    // allow time, start at i = 1 so that we don't call out own loop, ourorbourousing ourselves to death
+    for(let i = 1; i < hunks.length; i ++){
+      hunks[i].loop()
     }
-    */
+
   } // end loop
 
   /* ---------------------------    ---------------------------- */
@@ -643,13 +638,13 @@ function Manager() {
     }
     if (msgsout.ie && this.outmsgbuffer.length < 1) {
       // str8 shooters
-      if(msgdebug) this.log(`msg out ${header}`)
+      if (msgverbose) this.log(`msg out ${header}`)
       //console.log(content)
       msgsout.put(msg)
     } else {
       // gotta buffer
       this.outmsgbuffer.push(msg)
-      if(msgdebug) this.log(`MGR OUTBUFFER LEN IS ${this.outmsgbuffer.length}`)
+      if (msgverbose) this.log(`MGR OUTBUFFER LEN IS ${this.outmsgbuffer.length}`)
     }
   }
 }
diff --git a/hunks/view.js b/hunks/view.js
index 09c7138c6ecfcdfbcc93bb36c4267651054e057b..07fa1d3537beb37e7589c3b77c006cf29c7cfecb 100644
--- a/hunks/view.js
+++ b/hunks/view.js
@@ -25,11 +25,15 @@ function View() {
   Hunkify(this, 'View')
 
   let verbose = false
+  let msgverbose = false
 
   // view of a manager, has route to that manager (via a link?)
 
-  this.inputs.msgs = new Input('message', 'msgs')
-  this.outputs.msgs = new Output('message', 'msgs')
+  let msgsin = new Input('message', 'msgs')
+  let msgsout = new Output('message', 'msgs')
+
+  this.inputs.push(msgsin)
+  this.outputs.push(msgsout)
 
   // das UI globals
   // our dom is the space we're allotted,
@@ -53,9 +57,11 @@ function View() {
     this.plane = $('<div>').addClass('plane').get(0)
     // to log, type, etc
     this.msgbox = $('<div>').addClass('msgbox').get(0)
-    ze = $('<input/>').attr({type: 'checkbox'}).prop('checked', true).get(0)
+    ze = $('<input/>').attr({
+      type: 'checkbox'
+    }).prop('checked', true).get(0)
     $(ze).change(() => {
-      if($(ze).prop('checked')){
+      if ($(ze).prop('checked')) {
         zoomExtents()
       }
     })
@@ -102,11 +108,11 @@ function View() {
 
   let writeToMessageBox = (data) => {
     // write the message
-    this.msgbox.append($('<div>' + data + '</div>').addClass('msgboxmsg').get(0))
+    this.msgbox.append($('<div> -> ' + data + '</div>').addClass('msgboxmsg').get(0))
     // def check
     let heightcheck = () => {
       let height = 0;
-      $(this.msgbox).children().each(function(child){
+      $(this.msgbox).children().each(function(child) {
         // jquery.each() syntax is a bit odd / different than elsewhere, sorry for inconsistency
         height += this.clientHeight + 5
       })
@@ -114,11 +120,11 @@ function View() {
     }
     // if too tall, remove
     let ch = this.msgbox.clientHeight
-    if(heightcheck() > ch){
+    if (heightcheck() > ch) {
       console.log('rm 1', heightcheck(), ch)
       $(this.msgbox).children().get(1).remove()
       // two at most, sloppy but fast
-      if(heightcheck() > ch){
+      if (heightcheck() > ch) {
         console.log('rm 2', heightcheck(), ch)
         $(this.msgbox).children().get(1).remove()
       }
@@ -331,7 +337,7 @@ function View() {
       }
     }
     drawLinks()
-    if($(ze).prop('checked')){
+    if ($(ze).prop('checked')) {
       zoomExtents()
     }
   }
@@ -345,26 +351,32 @@ function View() {
     let psns = this.getAllHunkPositions()
     let sizes = this.getAllHunkSizes()
     // bless up, these are all in 0,0 relative space
-    let minxy = { x:0, y:0 }
-    let maxxy = { x:500, y:500 }
+    let minxy = {
+      x: 0,
+      y: 0
+    }
+    let maxxy = {
+      x: 500,
+      y: 500
+    }
     let maxx, minx, maxy, miny
-    for(let ind in psns){
+    for (let ind in psns) {
       maxx = psns[ind].x + sizes[ind].width
       minx = psns[ind].x
       maxy = psns[ind].y + sizes[ind].height
       miny = psns[ind].y
       // max cases
-      if(maxx > maxxy.x){
+      if (maxx > maxxy.x) {
         maxxy.x = maxx
       }
-      if(maxy > maxxy.y){
+      if (maxy > maxxy.y) {
         maxxy.y = maxy
       }
       // min cases
-      if(minx < minxy.x){
+      if (minx < minxy.x) {
         minxy.x = minx
       }
-      if(miny < minxy.y){
+      if (miny < minxy.y) {
         minxy.y = miny
       }
     }
@@ -384,8 +396,8 @@ function View() {
     let pfs = Math.min(pfsx, pfsy)
     // write em
     ct.s = pfs
-    ct.x = - minxy.x * pfs
-    ct.y = - minxy.y * pfs
+    ct.x = -minxy.x * pfs
+    ct.y = -minxy.y * pfs
     writeTransform(this.plane, ct)
     writeBackgroundTransform(this.dom, ct)
   }
@@ -406,7 +418,7 @@ function View() {
   this.getAllHunkSizes = () => {
     let nds = $(this.plane).children('.block')
     let sizes = new Array()
-    for (let nd of nds){
+    for (let nd of nds) {
       let ps = readSize(nd)
       ps.id = nd.id
       sizes.push(ps)
@@ -536,13 +548,13 @@ function View() {
     // hmmm ok,
     if (verbose) console.log('ready write', def)
     // do we have this id already? could be an update;
-    let mt
+    let mt = {}
     let match = $(this.plane).find('#' + def.id).get(0)
     let menu = $(this.plane).children('.contextmenu').get(0)
-    if(match !== undefined){
+    if (match !== undefined) {
       mt = readTransform(match)
       $(match).remove()
-    } else if (menu !== undefined){
+    } else if (menu !== undefined) {
       mt = readTransform(menu)
     } else {
       mt = {
@@ -558,7 +570,7 @@ function View() {
     // not interested in adding the top level's view to itself
     // TODO probably this is a bugfarm when we go to nest views
     if (def.dom !== null && def.dom !== undefined && def.id !== 'TLView') {
-      if(verbose) this.log(`${def.id} UI DOM appears...`, def.dom)
+      if (verbose) this.log(`${def.id} UI DOM appears...`, def.dom)
       try {
         $(de).append($(def.dom).addClass('cuttlefishhunkdom'))
         if ($(def.dom).is('.view')) {
@@ -741,6 +753,7 @@ function View() {
       }
       $(de).append(sdom)
     }
+
     return de
   }
 
@@ -752,7 +765,7 @@ function View() {
       $(this.plane).children(id).remove()
     }
     let dom = {}
-    if(inout === "input"){
+    if (inout === "input") {
       dom = $('<li>' + port.name + " (" + port.type + ")" + '</li>').addClass(inout).get(0)
     } else {
       dom = $('<li>' + "(" + port.type + ") " + port.name + '</li>').addClass(inout).get(0)
@@ -922,19 +935,17 @@ function View() {
 
   this.outmsgbuffer = new Array()
 
-  let msgdebug = false
-
   this.writemessage = (header, content) => {
     // guaranteed consumption here
     let msg = {
       header: header,
       content: content
     }
-    if (this.outputs.msgs.ie && this.outmsgbuffer.length < 1) {
+    if (msgsout.ie && this.outmsgbuffer.length < 1) {
       // str8 shooters
-      if(msgdebug) this.log('msg out', msg.header)
-      if(msgdebug) console.log(msg.content)
-      this.outputs.msgs.put(msg)
+      if (msgverbose) this.log('msg out', msg.header)
+      if (msgverbose) console.log(msg.content)
+      msgsout.put(msg)
     } else {
       // gotta buffer
       this.outmsgbuffer.push(msg)
@@ -950,15 +961,15 @@ function View() {
 
   this.loop = () => {
     // THE Q: is it trees or is it inputs / outputs ? ports ...
-    if (this.inputs.msgs.io) {
+    if (msgsin.io) {
       // HERE: this hack gets the data without a deep copy, so we want this
       // for bringing the dom element over *which is specific to a native manager*
       // so TODO: add switch for native / nonative managers
-      let data = this.inputs.msgs.data
-      let pult = this.inputs.msgs.get()
+      let data = msgsin.data
+      let pult = msgsin.get()
       let header = data.header
       let content = data.content
-      if(msgdebug) this.log(`gets msg ${header}`)
+      if (msgverbose) this.log(`gets msg ${header}`)
       switch (header) {
         case 'putcontextoptions':
           addContextOptions(content)