         # @todo wrap in an try/catch? or just let it bubble up?
         run.call(model)
 
-        # invoke watches and cull ones that request to be removed
-        # for speed, we just rewrite the portion of the list in place every time, eliminating cleared watches
-        # @todo surely, this should be wrapped in try/catch
-        watchCount = watchList.length
-        watchIndex = 0
-        compactedWatchCount = 0
-
-        while watchIndex < watchCount
-          watch = watchList[watchIndex]
-          watchIndex += 1
-
-          if not watch.isCleared
-            # preserve the watch for next run
-            watchList[compactedWatchCount] = watch
-            compactedWatchCount += 1
-
-            watch()
-
-        # truncate compacted watch list (preserving any watches that have been added during this run)
-        watchList.splice(compactedWatchCount, watchCount - compactedWatchCount)
-
-        console.log 'watch count', watchList.length
+        modelNotify()
 
     if preInitMap
       viewModel[n] = v for n, v of preInitMap

            v = if v is undefined then undefined else v[n]
          v

  runTemplate = (model, viewPrototype, template, preInitMap) ->
    viewModel =
      fork: (map, subTemplate) ->

        getter = createGetter model, path
        value = getter()

        clear = modelNotify ->
          # get and compare with cached values
          newValue = getter()
          if newValue isnt value
            value = newValue
            runTemplate value, viewModel, subTemplate

        runTemplate value, viewModel, subTemplate

        # return a handle to be able to unwatch
        { clear: clear }

      apply: (run) ->
        # fail fast on error
