diff --git a/strafe-client/src/mouse_interpolator.rs b/strafe-client/src/mouse_interpolator.rs
index c28665f..5f5b8bc 100644
--- a/strafe-client/src/mouse_interpolator.rs
+++ b/strafe-client/src/mouse_interpolator.rs
@@ -1,17 +1,15 @@
 use strafesnet_common::mouse::MouseState;
 use strafesnet_common::physics::{Instruction as PhysicsInputInstruction,Time as PhysicsTime,TimeInner as PhysicsTimeInner};
 use strafesnet_common::session::{Time as SessionTime,TimeInner as SessionTimeInner};
-use strafesnet_common::instruction::{self,InstructionConsumer,InstructionEmitter,TimedInstruction};
+use strafesnet_common::instruction::{InstructionConsumer,InstructionEmitter,TimedInstruction};
+
+use crate::session::StepInstruction as SessionInternalInstruction;
 
 type TimedPhysicsInstruction=TimedInstruction<PhysicsInputInstruction,PhysicsTimeInner>;
-type TimedInterpolatorInstruction=TimedInstruction<Instruction,SessionTimeInner>;
-
-pub struct DropInstruction<'a>{
-	instruction:&'a TimedPhysicsInstruction,
-}
+type TimedInterpolatorInstruction=TimedInstruction<UnbufferedInputInstruction,SessionTimeInner>;
 
 #[derive(Debug)]
-pub enum InputInstruction{
+pub enum UnbufferedInputInstruction{
 	MoveMouse(glam::IVec2),
 	MoveRight(bool),
 	MoveUp(bool),
@@ -26,52 +24,42 @@ pub enum InputInstruction{
 	PracticeFly,
 	Idle,
 }
-pub enum Instruction{
-	Input(InputInstruction),
-	//SetPaused is not an InputInstruction: the physics doesn't know that it's paused.
-	SetPaused(bool),
-	//Graphics(crate::graphics_worker::Instruction),
-}
 
 pub struct MouseInterpolator{
-	session_timeline:std::collections::VecDeque<TimedInterpolatorInstruction>,
 	physics_timeline:std::collections::VecDeque<TimedPhysicsInstruction>,
 }
 // Maybe MouseInterpolator manipulation is better expressed using impls
 // and called from Instruction trait impls in session
-impl InstructionConsumer<Instruction> for MouseInterpolator{
+impl InstructionConsumer<UnbufferedInputInstruction> for MouseInterpolator{
 	type TimeInner=SessionTimeInner;
 	fn process_instruction(&mut self,ins:TimedInterpolatorInstruction){
-		self.push_input(ins)
+		self.push_unbuffered_input(ins)
 	}
 }
-impl<'a> InstructionConsumer<DropInstruction<'a>> for MouseInterpolator{
+impl InstructionEmitter<SessionInternalInstruction> for MouseInterpolator{
 	type TimeInner=SessionTimeInner;
-	fn process_instruction(&mut self,ins:TimedInstruction<DropInstruction<'a>,SessionTimeInner>){
-		self.drop_output(ins)
-	}
-}
-impl<'a> InstructionEmitter<DropInstruction<'a>> for MouseInterpolator{
-	type TimeInner=SessionTimeInner;
-	fn next_instruction(&'a self,time_limit:SessionTime)->Option<TimedInstruction<DropInstruction<'a>,Self::TimeInner>>{
-		self.next_output(time_limit)
+	fn next_instruction(&self,time_limit:SessionTime)->Option<TimedInstruction<SessionInternalInstruction,Self::TimeInner>>{
+		self.buffered_instruction_with_timeout(time_limit)
 	}
 }
 impl MouseInterpolator{
 	pub fn new()->MouseInterpolator{
 		MouseInterpolator{
-			session_timeline:std::collections::VecDeque::new(),
 			physics_timeline:std::collections::VecDeque::new(),
 		}
 	}
-	pub fn push_input(&mut self,ins:TimedInterpolatorInstruction){
+	pub fn push_unbuffered_input(&mut self,ins:TimedInterpolatorInstruction){
 		// new input
 	}
-	pub fn drop_output<'a>(&mut self,ins:TimedInstruction<DropInstruction<'a>,SessionTimeInner>){
+	pub fn buffered_instruction_with_timeout(&self,time_limit:SessionTime)->Option<TimedInstruction<SessionInternalInstruction,SessionTimeInner>>{
+		// if the mouse has stopped moving for over 10ms, emit DoStepReplaceMouse
+		// if there is a mouse interpolation target, emit DoStep
+		// else emit None
+		None
+	}
+	pub fn pop_buffered_instruction(&mut self)->Option<TimedInstruction<PhysicsInputInstruction,PhysicsTimeInner>>{
 		// so the idea is that Session gets in the middle of MouseInterpolator instruction processing
 		// and injects its own side effects, notably running physics
-	}
-	pub fn next_output(&self,time_limit:SessionTime)->Option<TimedInstruction<DropInstruction<'_>,SessionTimeInner>>{
 		None
 	}
 }
diff --git a/strafe-client/src/session.rs b/strafe-client/src/session.rs
index 8e70397..a4a1440 100644
--- a/strafe-client/src/session.rs
+++ b/strafe-client/src/session.rs
@@ -1,23 +1,25 @@
-use strafesnet_common::instruction::{InstructionConsumer, InstructionEmitter};
+use strafesnet_common::instruction::{InstructionConsumer, InstructionEmitter, InstructionFeedback, TimedInstruction};
 // session represents the non-hardware state of the client.
 // Ideally it is a deterministic state which is atomically updated by instructions, same as the simulation state.
-use strafesnet_common::physics::{Instruction as PhysicsInputInstruction,Time as PhysicsTime};
+use strafesnet_common::physics::{Instruction as PhysicsInputInstruction,TimeInner as PhysicsTimeInner,Time as PhysicsTime};
 use strafesnet_common::timer::{Scaled,Timer};
-use strafesnet_common::physics::TimeInner as PhysicsTimeInner;
-use strafesnet_common::session::TimeInner as SessionTimeInner;
+use strafesnet_common::session::{TimeInner as SessionTimeInner,Time as SessionTime};
 
-use crate::mouse_interpolator::MouseInterpolator;
+use crate::mouse_interpolator::{MouseInterpolator,UnbufferedInputInstruction};
 
-pub enum Instruction{
-	Input(InputInstruction),
+pub enum ExternalInstruction{
+	ToBuffer(UnbufferedInputInstruction),
+	SetPaused(bool),
 	Render,
 	Resize(winit::dpi::PhysicalSize<u32>),
 	ChangeMap(strafesnet_common::map::CompleteMap),
-	//SetPaused is not an InputInstruction: the physics doesn't know that it's paused.
-	SetPaused(bool),
 	//Graphics(crate::graphics_worker::Instruction),
 }
 
+pub enum StepInstruction{
+	DoStep,
+}
+
 pub struct FrameState{
 	pub body:crate::physics::Body,
 	pub camera:crate::physics::PhysicsCamera,
@@ -81,28 +83,49 @@ impl Session{
 
 // mouseinterpolator consumes RawInputInstruction
 // mouseinterpolator emits PhysicsInputInstruction
-// mouseinterpolator consumes DropInstruction to move on to the next emitted instruction
+// mouseinterpolator consumes DoStep to move on to the next emitted instruction
 // Session comsumes SessionInstruction -> forwards RawInputInstruction to mouseinterpolator
-// Session consumes DropInstruction -> forwards DropInstruction to mouseinterpolator
-// Session emits DropInstruction
+// Session consumes DoStep -> forwards DoStep to mouseinterpolator
+// Session emits DoStep
 
-impl InstructionConsumer<Instruction> for Session{
+impl InstructionConsumer<ExternalInstruction> for Session{
 	type TimeInner=SessionTimeInner;
-	fn process_instruction(&mut self,instruction:strafesnet_common::instruction::TimedInstruction<Instruction,Self::TimeInner>){
-		// send it down to MouseInterpolator
-		self.mouse_interpolator.process_instruction(ins);
+	fn process_instruction(&mut self,ins:TimedInstruction<ExternalInstruction,Self::TimeInner>){
+		match ins.instruction{
+			// send it down to MouseInterpolator
+			ExternalInstruction::ToBuffer(instruction)=>self.mouse_interpolator.process_instruction(TimedInstruction{
+				time:ins.time,
+				instruction,
+			}),
+			ExternalInstruction::SetPaused(paused)=>{
+				// don't flush the buffered instructions in the mouse interpolator
+				// until the mouse is confirmed to be not moving at a later time
+				// what if they pause for 5ms lmao
+				_=self.simulation.timer.set_paused(ins.time,paused);
+			}
+			ExternalInstruction::Render=>(),
+			ExternalInstruction::Resize(physical_size)=>(),
+			ExternalInstruction::ChangeMap(complete_map)=>(),
+		};
+		// run all buffered instruction produced
+		self.process_exhaustive(ins.time);
 	}
 }
-impl<'a> InstructionConsumer<DropInstruction<'a>> for Session{
+impl InstructionConsumer<StepInstruction> for Session{
 	type TimeInner=SessionTimeInner;
-	fn process_instruction(&mut self,instruction:strafesnet_common::instruction::TimedInstruction<DropInstruction,Self::TimeInner>){
-		// send it down to MouseInterpolator
-		self.mouse_interpolator.process_instruction(ins);
+	fn process_instruction(&mut self,ins:TimedInstruction<StepInstruction,Self::TimeInner>){
+		match ins.instruction{
+			StepInstruction::DoStep=>{
+				if let Some(instruction)=self.mouse_interpolator.pop_buffered_instruction(){
+					self.simulation.physics.run_input_instruction(instruction);
+				}
+			}
+		}
 	}
 }
-impl<'a> InstructionEmitter<DropInstruction<'a>> for Session{
+impl InstructionEmitter<StepInstruction> for Session{
 	type TimeInner=SessionTimeInner;
-	fn next_instruction(&self,time_limit:strafesnet_common::integer::Time<Self::TimeInner>)->Option<strafesnet_common::instruction::TimedInstruction<DropInstruction,Self::TimeInner>>{
+	fn next_instruction(&self,time_limit:SessionTime)->Option<TimedInstruction<StepInstruction,Self::TimeInner>>{
 		self.mouse_interpolator.next_instruction(time_limit)
 	}
 }