Shared memory and context tools for agentic work.
Code Rooms
// === m1nd-mcp/src/protocol/lock.rs ===
// Input/Output types for the 5 lock MCP tools.
// From 12-PERSPECTIVE-SYNTHESIS Themes 2, 4, 10, 14.
use serde::{Deserialize, Serialize};
use crate::perspective::state::{LockDiffResult, LockScope, LockState, WatchStrategy};
// ---------------------------------------------------------------------------
// lock.create (Theme 2, 14)
#[derive(Clone, Debug, Deserialize)]
pub struct LockCreateInput {
pub agent_id: String,
/// Scope type: node, subgraph, query_neighborhood, path.
pub scope: LockScope,
/// Root nodes for the lock scope. Non-empty required.
pub root_nodes: Vec<String>,
/// BFS radius for subgraph scope. Min 1, max 4.
#[serde(default)]
pub radius: Option<u32>,
/// Query string for query_neighborhood scope.
pub query: Option<String>,
/// Ordered node list for path scope.
pub path_nodes: Option<Vec<String>>,
}
#[derive(Clone, Debug, Serialize)]
pub struct LockCreateOutput {
pub lock_id: String,
pub baseline_nodes: usize,
pub baseline_edges: usize,
pub graph_generation: u64,
pub created_at_ms: u64,
pub proof_state: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_suggested_tool: Option<String>,
pub next_suggested_target: Option<String>,
pub next_step_hint: Option<String>,
// lock.watch (Theme 10)
pub struct LockWatchInput {
/// Strategy: manual, on_ingest, on_learn. Periodic returns error.
pub strategy: WatchStrategy,
pub struct LockWatchOutput {
/// Previous strategy if one was replaced.
pub previous_strategy: Option<WatchStrategy>,
// lock.diff (Theme 14)
pub struct LockDiffInput {
pub struct LockDiffOutput {
pub diff: LockDiffResult,
/// Whether watcher events were drained for this diff.
pub watcher_events_drained: usize,
/// If baseline_stale, suggest lock.rebase.
pub rebase_suggested: Option<String>,
// lock.rebase (Theme 14 — new tool)
pub struct LockRebaseInput {
pub struct LockRebaseOutput {
pub previous_generation: u64,
pub new_generation: u64,
/// Watcher config preserved across rebase.
pub watcher_preserved: bool,
// lock.release (Theme 14)
pub struct LockReleaseInput {
pub struct LockReleaseOutput {
pub released: bool,
// Tests
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn lock_create_input_deserializes_node_scope() {
let json = r#"{
"agent_id": "jimi",
"scope": "node",
"root_nodes": ["session.rs"]
}"#;
let input: LockCreateInput = serde_json::from_str(json).unwrap();
assert_eq!(input.scope, LockScope::Node);
assert_eq!(input.root_nodes.len(), 1);
assert!(input.radius.is_none());
fn lock_create_input_deserializes_subgraph_scope() {
"scope": "subgraph",
"root_nodes": ["session.rs"],
"radius": 2
assert_eq!(input.scope, LockScope::Subgraph);
assert_eq!(input.radius, Some(2));
fn lock_watch_input_deserializes() {
let json = r#"{"agent_id": "jimi", "lock_id": "lock_jimi_001", "strategy": "on_ingest"}"#;
let input: LockWatchInput = serde_json::from_str(json).unwrap();
assert_eq!(input.strategy, WatchStrategy::OnIngest);
fn lock_diff_input_minimal() {
let json = r#"{"agent_id": "jimi", "lock_id": "lock_jimi_001"}"#;
let input: LockDiffInput = serde_json::from_str(json).unwrap();
assert_eq!(input.lock_id, "lock_jimi_001");
fn lock_release_input_minimal() {
let input: LockReleaseInput = serde_json::from_str(json).unwrap();