     :keys [::specs/message-loop-name]
     :as state}]
   {:pre [callback]}
-  (let [prelog (utils/pre-log message-loop-name)]
-    (log/info prelog
-              "trigger-from-child"
-              "\nSent stream address:"
-              strm-hwm)
+  (let [state (update state
+                      ::log2/state
+                      #(log2/info %
+                                  ::trigger-from-child
+                                  "Sent stream address"
+                                  {::specs/strm-hwm strm-hwm
+                                   ::specs/message-loop-name message-loop-name}))]
     (deliver accepted? true)
     (let [state' (callback state)]
       ;; TODO: check whether we can do output now.

                          "Top of scheduler at ~:d"
                          now))
    (if (not (strm/closed? stream))
      (let [actual-next
            ;; TODO: Reframe this logic around
            ;; whether child-input-loop and
            ;; child-output-loop have been realized

        ;; TODO: Compare with other higher-level implementations
        ;; TODO: Ask cryptographers and protocol experts whether this is
        ;; a choice I'll really regret
        state (assoc state ::specs/recent now)
        log-state
        (try
          (log2/debug log-state
                      ::action-trigger
                      (cl-format nil
                                 fmt
                                 delta_f
                                 scheduling-time
                                 (or actual-next -1)
                                 now
                                 success))
          (catch NullPointerException ex
            (log2/exception log-state
                            ex
                            ::action-trigger
                            "Error building the event loop Awakening message"
                            {::delta_f delta_f
                             ::scheduling-time scheduling-time
                             ::actual-next actual-next
                             ::now now
                             ::success success}))
          (catch NumberFormatException ex
            (log2/exception log-state
                            ex
                            ::action-trigger
                            "Error formatting the event loop Awakening message"
                            {::delta_f delta_f
                             ::scheduling-time scheduling-time
                             ::actual-next actual-next
                             ::now now
                             ::success success})))
        [tag
         log-state] (try [(first success) log-state]
                         (catch IllegalArgumentException ex
                           [::no-op
                            (log2/exception log-state
                                            ex
                                            ::action-trigger
                                            "Should have been a variant")]))
        ;; TODO: Really should add something like a transaction ID to the state
        ;; to assist in tracing the action
        updater
        ;; Q: Is this worth switching to something like core.match or a multimethod?
        (case tag
          ::specs/child-> (let [[_ callback ack] success]
                            (partial trigger-from-child io-handle callback ack))
          ::drained (do (throw (RuntimeException. "Start back here, after I've checked handshake test"))
                        (log/warn prelog
                                  ;; Actually, this seems like a strong argument for
                                  ;; having a pair of streams. Child could still have
                                  ;; bytes to send to the parent after the latter's
                                  ;; stopped sending, or vice versa.
                                  ;; I'm pretty sure the complexity I haven't finished
                                  ;; translating stems from that case.
                                  ;; TODO: Another piece to revisit once the basics
                                  ;; work.
                                  "Stream closed. Surely there's more to do")
                        (constantly nil))
          ::parent-> (partial trigger-from-parent
                              io-handle
                              (second success))
          ::no-op identity
          ;; This can throw off the timer, since we're basic the delay on
          ;; the delta from recent (which doesn't change) rather than now.
          ;; But we're basing the actual delay from now, which does change.
          ;; e.g. If the scheduled delay is 980 ms, and someone triggers a
          ;; query-state that takes 20 ms after 20 ms, the new delay will
          ;; still be 980 ms rather than the 940 that would have been
          ;; appropriate.
          ;; Q: What's the best way to avoid this?
          ::query-state (fn [state]
                          (if-let [dst (second success)]
                            (deliver dst state)
                            (log/warn prelog "state-query request missing required deferred"))
                          state)
          ::timed-out (do
                        (log/debug prelog
                                   (cl-format nil
                                              "Timer for ~:d ms after ~:d timed out. Re-triggering Output"
                                              delta_f
                                              scheduling-time))
                        (partial trigger-from-timer io-handle)))]
    (when (not= tag ::drained)
      (log/debug prelog "Processing event:" tag)
      ;; At the end of the main ioloop in the refernce
      ;; implementation, there's a block that closes the pipe
      ;; to the child if we're done.
      ;; I think the point is that we'll quit polling on
      ;; that and start short-circuiting out of the blocks
      ;; that might do the send, once we've hit EOF
      ;; Q: What can I do here to
      ;; produce the same effect?
      ;; TODO: Worry about that once the basic idea works.

      ;; If the child sent a big batch of data to go out
      ;; all at once, don't waste time setting up a timeout
      ;; scheduler. The poll in the original would have
      ;; returned immediately anyway.
      ;; Except that n-sec-per-block puts a hard limit on how
      ;; fast we can send.
      (let [start (System/nanoTime)
            ;; TODO: Break these pieces into something
            ;; like the interceptor-chain idea. They should
            ;; return a value that includes a key for a
            ;; seq of functions to run to perform the
            ;; side-effects.
            ;; I'd still have to call updater, get
            ;; that updating seq, and update the state
            ;; to recurse.

            ;; I'd prefer to do these next two
            ;; pieces in a single step.

            ;; TODO: Read up on Executors. I could wind up
            ;; with really nasty interactions now that I
            ;; don't have an agent to keep this single-
            ;; threaded.
            ;; Actually, it should be safe as written.
            ;; Just be sure to keep everything synchronized
            ;; around takes from the i/o handle. (Not
            ;; needing to do that manually is
            ;; a great reason to not introduce a second
            ;; one for bytes travelling the other direction)
            state' (try (updater state)
                        (catch ExceptionInfo ex
                          (log/error ex
                                     (str
                                      prelog
                                      "Running updater failed.\nDetails:\n"
                                      (.getData ex))))
                        (catch RuntimeException ex
                          (log/error ex
                                     prelog
                                     "Running updater failed")
                          ;; The eternal question in this scenario:
                          ;; Fail fast, or hope we can keep limping
                          ;; along?
                          ;; TODO: Add prod vs. dev environment options
                          ;; to give the caller control over what
                          ;; should happen here.
                          ;; (Note that, either way, it really should
                          ;; include a callback to some
                          ;; currently-undefined status updater
                          (comment state)))
            state' (update state'
                           ::log2/state
                           #(log2/flush-logs! (::log2/logger io-handle) %))
            mid (System/nanoTime)
            ;; This is taking a ludicrous amount of time.
            ;; Q: How much should I blame on logging?
            _ (schedule-next-timeout! io-handle state')
            end (System/nanoTime)]
        ;; FIXME: This needs to change to new logging system.
        ;; Although, really, that's more trouble than it's worth.
        ;; I'd have to fork the logs to send one half to schedule-next-timeout!
        ;; and then flush this again.
        ;; Better to fix my scheduling mismatch and just ditch my initial approach.
        (log/debug prelog
                   (cl-format nil
                              (str
                               "Handling ~a event took ~:d nanoseconds\n"
                               "Scheduling next timeout took ~:d  nanoseconds")
                              tag
                              (- mid start)
                              (- end mid)))
        nil))))

(comment
  (let [delta_f ##Inf,
