Rename mind/dmn.rs to mind/subconscious.rs

The file contains both the DMN state machine and the subconscious agent
orchestration. Renaming to match the conceptual grouping — next step is
adding mind/unconscious.rs for the standalone graph maintenance agents
(organize, linker, etc.) that don't need conversation context.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
ProofOfConcept 2026-04-08 23:37:01 -04:00
parent 24b211dc35
commit 9704e7a698
4 changed files with 28 additions and 28 deletions

View file

@ -4,7 +4,7 @@
// Everything about how the mind operates, separate from the // Everything about how the mind operates, separate from the
// user interface (TUI, CLI) and the agent execution (tools, API). // user interface (TUI, CLI) and the agent execution (tools, API).
pub mod dmn; pub mod subconscious;
pub mod identity; pub mod identity;
pub mod log; pub mod log;
@ -26,7 +26,7 @@ use crate::agent::api::ApiClient;
use crate::config::{AppConfig, SessionConfig}; use crate::config::{AppConfig, SessionConfig};
use crate::subconscious::learn; use crate::subconscious::learn;
pub use dmn::{SubconsciousSnapshot, Subconscious}; pub use subconscious::{SubconsciousSnapshot, Subconscious};
use crate::agent::context::{AstNode, NodeBody, Section, Ast, ContextState}; use crate::agent::context::{AstNode, NodeBody, Section, Ast, ContextState};
@ -98,7 +98,7 @@ pub struct MindState {
/// True while a turn is in progress. /// True while a turn is in progress.
pub turn_active: bool, pub turn_active: bool,
/// DMN state /// DMN state
pub dmn: dmn::State, pub dmn: subconscious::State,
pub dmn_turns: u32, pub dmn_turns: u32,
pub max_dmn_turns: u32, pub max_dmn_turns: u32,
/// Whether memory scoring is running. /// Whether memory scoring is running.
@ -150,8 +150,8 @@ impl MindState {
Self { Self {
input: Vec::new(), input: Vec::new(),
turn_active: false, turn_active: false,
dmn: if dmn::is_off() { dmn::State::Off } dmn: if subconscious::is_off() { subconscious::State::Off }
else { dmn::State::Resting { since: Instant::now() } }, else { subconscious::State::Resting { since: Instant::now() } },
dmn_turns: 0, dmn_turns: 0,
max_dmn_turns, max_dmn_turns,
scoring_in_flight: false, scoring_in_flight: false,
@ -175,7 +175,7 @@ impl MindState {
self.dmn_turns = 0; self.dmn_turns = 0;
self.consecutive_errors = 0; self.consecutive_errors = 0;
self.last_user_input = Instant::now(); self.last_user_input = Instant::now();
self.dmn = dmn::State::Engaged; self.dmn = subconscious::State::Engaged;
Some(text) Some(text)
} }
@ -190,21 +190,21 @@ impl MindState {
self.consecutive_errors = 0; self.consecutive_errors = 0;
} }
self.last_turn_had_tools = turn_result.had_tool_calls; self.last_turn_had_tools = turn_result.had_tool_calls;
self.dmn = dmn::transition( self.dmn = subconscious::transition(
&self.dmn, &self.dmn,
turn_result.yield_requested, turn_result.yield_requested,
turn_result.had_tool_calls, turn_result.had_tool_calls,
target == StreamTarget::Conversation, target == StreamTarget::Conversation,
); );
if turn_result.dmn_pause { if turn_result.dmn_pause {
self.dmn = dmn::State::Paused; self.dmn = subconscious::State::Paused;
self.dmn_turns = 0; self.dmn_turns = 0;
} }
turn_result.model_switch.clone() turn_result.model_switch.clone()
} }
Err(_) => { Err(_) => {
self.consecutive_errors += 1; self.consecutive_errors += 1;
self.dmn = dmn::State::Resting { since: Instant::now() }; self.dmn = subconscious::State::Resting { since: Instant::now() };
None None
} }
} }
@ -212,18 +212,18 @@ impl MindState {
/// DMN tick — returns a prompt and target if we should run a turn. /// DMN tick — returns a prompt and target if we should run a turn.
fn dmn_tick(&mut self) -> Option<(String, StreamTarget)> { fn dmn_tick(&mut self) -> Option<(String, StreamTarget)> {
if matches!(self.dmn, dmn::State::Paused | dmn::State::Off) { if matches!(self.dmn, subconscious::State::Paused | subconscious::State::Off) {
return None; return None;
} }
self.dmn_turns += 1; self.dmn_turns += 1;
if self.dmn_turns > self.max_dmn_turns { if self.dmn_turns > self.max_dmn_turns {
self.dmn = dmn::State::Resting { since: Instant::now() }; self.dmn = subconscious::State::Resting { since: Instant::now() };
self.dmn_turns = 0; self.dmn_turns = 0;
return None; return None;
} }
let dmn_ctx = dmn::DmnContext { let dmn_ctx = subconscious::DmnContext {
user_idle: self.last_user_input.elapsed(), user_idle: self.last_user_input.elapsed(),
consecutive_errors: self.consecutive_errors, consecutive_errors: self.consecutive_errors,
last_turn_had_tools: self.last_turn_had_tools, last_turn_had_tools: self.last_turn_had_tools,
@ -234,7 +234,7 @@ impl MindState {
fn interrupt(&mut self) { fn interrupt(&mut self) {
self.input.clear(); self.input.clear();
self.dmn = dmn::State::Resting { since: Instant::now() }; self.dmn = subconscious::State::Resting { since: Instant::now() };
} }
} }
@ -360,7 +360,7 @@ impl Mind {
MindCommand::NewSession => { MindCommand::NewSession => {
{ {
let mut s = self.shared.lock().unwrap(); let mut s = self.shared.lock().unwrap();
s.dmn = dmn::State::Resting { since: Instant::now() }; s.dmn = subconscious::State::Resting { since: Instant::now() };
s.dmn_turns = 0; s.dmn_turns = 0;
} }
let new_log = log::ConversationLog::new( let new_log = log::ConversationLog::new(

View file

@ -68,22 +68,22 @@ fn commands() -> Vec<SlashCommand> { vec![
SlashCommand { name: "/sleep", help: "Put DMN to sleep", SlashCommand { name: "/sleep", help: "Put DMN to sleep",
handler: |s, _| { handler: |s, _| {
let mut st = s.shared_mind.lock().unwrap(); let mut st = s.shared_mind.lock().unwrap();
st.dmn = crate::mind::dmn::State::Resting { since: std::time::Instant::now() }; st.dmn = crate::mind::subconscious::State::Resting { since: std::time::Instant::now() };
st.dmn_turns = 0; st.dmn_turns = 0;
if let Ok(mut ag) = s.agent.state.try_lock() { ag.notify("DMN sleeping"); } if let Ok(mut ag) = s.agent.state.try_lock() { ag.notify("DMN sleeping"); }
} }, } },
SlashCommand { name: "/wake", help: "Wake DMN to foraging", SlashCommand { name: "/wake", help: "Wake DMN to foraging",
handler: |s, _| { handler: |s, _| {
let mut st = s.shared_mind.lock().unwrap(); let mut st = s.shared_mind.lock().unwrap();
if matches!(st.dmn, crate::mind::dmn::State::Off) { crate::mind::dmn::set_off(false); } if matches!(st.dmn, crate::mind::subconscious::State::Off) { crate::mind::subconscious::set_off(false); }
st.dmn = crate::mind::dmn::State::Foraging; st.dmn = crate::mind::subconscious::State::Foraging;
st.dmn_turns = 0; st.dmn_turns = 0;
if let Ok(mut ag) = s.agent.state.try_lock() { ag.notify("DMN foraging"); } if let Ok(mut ag) = s.agent.state.try_lock() { ag.notify("DMN foraging"); }
} }, } },
SlashCommand { name: "/pause", help: "Full stop — no autonomous ticks (Ctrl+P)", SlashCommand { name: "/pause", help: "Full stop — no autonomous ticks (Ctrl+P)",
handler: |s, _| { handler: |s, _| {
let mut st = s.shared_mind.lock().unwrap(); let mut st = s.shared_mind.lock().unwrap();
st.dmn = crate::mind::dmn::State::Paused; st.dmn = crate::mind::subconscious::State::Paused;
st.dmn_turns = 0; st.dmn_turns = 0;
if let Ok(mut ag) = s.agent.state.try_lock() { ag.notify("DMN paused"); } if let Ok(mut ag) = s.agent.state.try_lock() { ag.notify("DMN paused"); }
} }, } },

View file

@ -232,22 +232,22 @@ async fn hotkey_kill_processes(mind: &crate::mind::Mind) {
fn hotkey_cycle_autonomy(mind: &crate::mind::Mind) { fn hotkey_cycle_autonomy(mind: &crate::mind::Mind) {
let mut s = mind.shared.lock().unwrap(); let mut s = mind.shared.lock().unwrap();
let label = match &s.dmn { let label = match &s.dmn {
crate::mind::dmn::State::Engaged | crate::mind::dmn::State::Working | crate::mind::dmn::State::Foraging => { crate::mind::subconscious::State::Engaged | crate::mind::subconscious::State::Working | crate::mind::subconscious::State::Foraging => {
s.dmn = crate::mind::dmn::State::Resting { since: std::time::Instant::now() }; s.dmn = crate::mind::subconscious::State::Resting { since: std::time::Instant::now() };
"resting" "resting"
} }
crate::mind::dmn::State::Resting { .. } => { crate::mind::subconscious::State::Resting { .. } => {
s.dmn = crate::mind::dmn::State::Paused; s.dmn = crate::mind::subconscious::State::Paused;
"PAUSED" "PAUSED"
} }
crate::mind::dmn::State::Paused => { crate::mind::subconscious::State::Paused => {
crate::mind::dmn::set_off(true); crate::mind::subconscious::set_off(true);
s.dmn = crate::mind::dmn::State::Off; s.dmn = crate::mind::subconscious::State::Off;
"OFF (persists across restarts)" "OFF (persists across restarts)"
} }
crate::mind::dmn::State::Off => { crate::mind::subconscious::State::Off => {
crate::mind::dmn::set_off(false); crate::mind::subconscious::set_off(false);
s.dmn = crate::mind::dmn::State::Foraging; s.dmn = crate::mind::subconscious::State::Foraging;
"foraging" "foraging"
} }
}; };