diff --git a/poc-memory/src/cli/graph.rs b/poc-memory/src/cli/graph.rs index 59f6111..6fceb2c 100644 --- a/poc-memory/src/cli/graph.rs +++ b/poc-memory/src/cli/graph.rs @@ -134,6 +134,7 @@ pub fn cmd_triangle_close(min_degree: usize, sim_threshold: f32, max_per_hub: us } pub fn cmd_link_add(source: &str, target: &str, reason: &[String]) -> Result<(), String> { + super::check_dry_run(); let mut store = store::Store::load()?; let source = store.resolve_key(source)?; let target = store.resolve_key(target)?; diff --git a/poc-memory/src/cli/journal.rs b/poc-memory/src/cli/journal.rs index 182f331..b81ca22 100644 --- a/poc-memory/src/cli/journal.rs +++ b/poc-memory/src/cli/journal.rs @@ -176,6 +176,7 @@ pub fn cmd_journal_write(text: &[String]) -> Result<(), String> { if text.is_empty() { return Err("journal-write requires text".into()); } + super::check_dry_run(); let text = text.join(" "); let timestamp = crate::store::format_datetime(crate::store::now_epoch()); diff --git a/poc-memory/src/cli/mod.rs b/poc-memory/src/cli/mod.rs index 4d111d8..2020e55 100644 --- a/poc-memory/src/cli/mod.rs +++ b/poc-memory/src/cli/mod.rs @@ -9,3 +9,10 @@ pub mod agent; pub mod admin; pub mod journal; pub mod misc; + +/// Exit silently if POC_MEMORY_DRY_RUN=1. +pub fn check_dry_run() { + if std::env::var("POC_MEMORY_DRY_RUN").map_or(false, |v| v == "1" || v == "true") { + std::process::exit(0); + } +} diff --git a/poc-memory/src/cli/node.rs b/poc-memory/src/cli/node.rs index a6ee1c4..697e2be 100644 --- a/poc-memory/src/cli/node.rs +++ b/poc-memory/src/cli/node.rs @@ -11,6 +11,7 @@ pub fn cmd_used(key: &[String]) -> Result<(), String> { if key.is_empty() { return Err("used requires a key".into()); } + super::check_dry_run(); let key = key.join(" "); let mut store = store::Store::load()?; let resolved = store.resolve_key(&key)?; @@ -38,6 +39,7 @@ pub fn cmd_used(key: &[String]) -> Result<(), String> { pub fn cmd_wrong(key: &str, context: &[String]) -> Result<(), String> { let ctx = if context.is_empty() { None } else { Some(context.join(" ")) }; + super::check_dry_run(); let mut store = store::Store::load()?; let resolved = store.resolve_key(key)?; store.mark_wrong(&resolved, ctx.as_deref()); @@ -71,6 +73,8 @@ pub fn cmd_not_relevant(key: &str) -> Result<(), String> { } pub fn cmd_not_useful(key: &str) -> Result<(), String> { + // no args to validate + super::check_dry_run(); let mut store = store::Store::load()?; let resolved = store.resolve_key(key)?; // Same as wrong but with clearer semantics: node content is bad, edges are fine. @@ -84,6 +88,7 @@ pub fn cmd_gap(description: &[String]) -> Result<(), String> { if description.is_empty() { return Err("gap requires a description".into()); } + super::check_dry_run(); let desc = description.join(" "); let mut store = store::Store::load()?; store.record_gap(&desc); @@ -146,6 +151,7 @@ pub fn cmd_node_delete(key: &[String]) -> Result<(), String> { if key.is_empty() { return Err("node-delete requires a key".into()); } + super::check_dry_run(); let key = key.join(" "); let mut store = store::Store::load()?; let resolved = store.resolve_key(&key)?; @@ -156,6 +162,8 @@ pub fn cmd_node_delete(key: &[String]) -> Result<(), String> { } pub fn cmd_node_rename(old_key: &str, new_key: &str) -> Result<(), String> { + // args are positional, always valid if present + super::check_dry_run(); let mut store = store::Store::load()?; let old_resolved = store.resolve_key(old_key)?; store.rename_node(&old_resolved, new_key)?; @@ -286,6 +294,7 @@ pub fn cmd_write(key: &[String]) -> Result<(), String> { if content.trim().is_empty() { return Err("No content on stdin".into()); } + super::check_dry_run(); let mut store = store::Store::load()?; let key = store.resolve_key(&raw_key).unwrap_or(raw_key);