This change removes the legacy logs/ directory and consolidates all session data, error logs, and discovery files under the .g3/ directory. New directory structure: - .g3/sessions/<session_id>/session.json - session logs - .g3/errors/ - error logs (was logs/errors/) - .g3/background_processes/ - background process logs - .g3/discovery/ - planner discovery files (was workspace/logs/) Changes: - paths.rs: Remove get_logs_dir()/logs_dir(), add get_errors_dir(), get_background_processes_dir(), get_discovery_dir() - session.rs: Anonymous sessions now use .g3/sessions/anonymous_<ts>/ - error_handling.rs: Errors now saved to .g3/errors/ - project.rs: Remove logs_dir() and ensure_logs_dir() methods - feedback_extraction.rs: Remove logs_dir field and fallback logic - planner: Use .g3/ for workspace data and .g3/discovery/ for reports - flock.rs: Look for session metrics in .g3/sessions/ - coach_feedback.rs: Remove fallback to logs/ path - Update all tests to use new paths - Update README.md and .gitignore
147 lines
5.0 KiB
Rust
147 lines
5.0 KiB
Rust
//! Path utilities for G3 session and workspace management.
|
|
//!
|
|
//! This module centralizes all path-related logic for:
|
|
//! - TODO file location
|
|
//! - Error logs directory
|
|
//! - Session directories and files
|
|
//! - Thinned content storage
|
|
|
|
use std::path::PathBuf;
|
|
|
|
/// Environment variable name for workspace path.
|
|
/// Used to direct all logs to the workspace directory.
|
|
pub const G3_WORKSPACE_PATH_ENV: &str = "G3_WORKSPACE_PATH";
|
|
|
|
/// Environment variable name for custom TODO file path.
|
|
const G3_TODO_PATH_ENV: &str = "G3_TODO_PATH";
|
|
|
|
/// Get the path to the todo.g3.md file.
|
|
///
|
|
/// Checks for G3_TODO_PATH environment variable first (used by planning mode),
|
|
/// then falls back to todo.g3.md in the current directory.
|
|
pub fn get_todo_path() -> PathBuf {
|
|
if let Ok(custom_path) = std::env::var(G3_TODO_PATH_ENV) {
|
|
PathBuf::from(custom_path)
|
|
} else {
|
|
std::env::current_dir().unwrap_or_default().join("todo.g3.md")
|
|
}
|
|
}
|
|
|
|
/// Get the path to the todo.g3.md file for a specific session.
|
|
/// Returns .g3/sessions/<session_id>/todo.g3.md
|
|
pub fn get_session_todo_path(session_id: &str) -> PathBuf {
|
|
get_session_logs_dir(session_id).join("todo.g3.md")
|
|
}
|
|
|
|
/// Get the path to the errors directory.
|
|
///
|
|
/// Returns `.g3/errors/` in the workspace or current directory.
|
|
pub fn get_errors_dir() -> PathBuf {
|
|
get_g3_dir().join("errors")
|
|
}
|
|
|
|
/// Get the path to the background processes directory.
|
|
///
|
|
/// Returns `.g3/background_processes/` in the workspace or current directory.
|
|
pub fn get_background_processes_dir() -> PathBuf {
|
|
get_g3_dir().join("background_processes")
|
|
}
|
|
|
|
/// Get the path to the discovery logs directory (for planner mode).
|
|
///
|
|
/// Returns `.g3/discovery/` in the workspace or current directory.
|
|
pub fn get_discovery_dir() -> PathBuf {
|
|
if let Ok(workspace_path) = std::env::var(G3_WORKSPACE_PATH_ENV) {
|
|
PathBuf::from(workspace_path).join(".g3").join("discovery")
|
|
} else {
|
|
get_g3_dir().join("discovery")
|
|
}
|
|
}
|
|
|
|
/// Get the base .g3 directory path.
|
|
/// This is the root for all g3 session data in the current workspace.
|
|
pub fn get_g3_dir() -> PathBuf {
|
|
if let Ok(workspace_path) = std::env::var(G3_WORKSPACE_PATH_ENV) {
|
|
PathBuf::from(workspace_path).join(".g3")
|
|
} else {
|
|
std::env::current_dir().unwrap_or_default().join(".g3")
|
|
}
|
|
}
|
|
|
|
/// Get the session directory for a specific session ID.
|
|
/// Returns .g3/sessions/<session_id>/
|
|
pub fn get_session_logs_dir(session_id: &str) -> PathBuf {
|
|
get_g3_dir().join("sessions").join(session_id)
|
|
}
|
|
|
|
/// Ensure the session directory exists for a specific session ID.
|
|
/// Creates .g3/sessions/<session_id>/ and subdirectories.
|
|
pub fn ensure_session_dir(session_id: &str) -> std::io::Result<PathBuf> {
|
|
let session_dir = get_session_logs_dir(session_id);
|
|
std::fs::create_dir_all(&session_dir)?;
|
|
|
|
// Create subdirectories
|
|
std::fs::create_dir_all(session_dir.join("thinned"))?;
|
|
|
|
Ok(session_dir)
|
|
}
|
|
|
|
/// Get the thinned content directory for a session.
|
|
/// Returns .g3/sessions/<session_id>/thinned/
|
|
pub fn get_thinned_dir(session_id: &str) -> PathBuf {
|
|
get_session_logs_dir(session_id).join("thinned")
|
|
}
|
|
|
|
/// Get the fragments directory for a session (for ACD dehydrated context).
|
|
/// Returns .g3/sessions/<session_id>/fragments/
|
|
pub fn get_fragments_dir(session_id: &str) -> PathBuf {
|
|
get_session_logs_dir(session_id).join("fragments")
|
|
}
|
|
|
|
/// Get the path to the session.json file for a session.
|
|
/// Returns .g3/sessions/<session_id>/session.json
|
|
pub fn get_session_file(session_id: &str) -> PathBuf {
|
|
get_session_logs_dir(session_id).join("session.json")
|
|
}
|
|
|
|
/// Get the path to the context summary file for a session.
|
|
/// Returns .g3/sessions/<session_id>/context_summary.txt
|
|
pub fn get_context_summary_file(session_id: &str) -> PathBuf {
|
|
get_session_logs_dir(session_id).join("context_summary.txt")
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_todo_path_default() {
|
|
// When G3_TODO_PATH is not set, should return current_dir/todo.g3.md
|
|
std::env::remove_var(G3_TODO_PATH_ENV);
|
|
let path = get_todo_path();
|
|
assert!(path.ends_with("todo.g3.md"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_session_paths_are_consistent() {
|
|
let session_id = "test-session-123";
|
|
let session_dir = get_session_logs_dir(session_id);
|
|
let thinned_dir = get_thinned_dir(session_id);
|
|
let session_file = get_session_file(session_id);
|
|
let summary_file = get_context_summary_file(session_id);
|
|
let todo_file = get_session_todo_path(session_id);
|
|
|
|
// All paths should be under the session directory
|
|
assert!(thinned_dir.starts_with(&session_dir));
|
|
assert!(session_file.starts_with(&session_dir));
|
|
assert!(summary_file.starts_with(&session_dir));
|
|
assert!(todo_file.starts_with(&session_dir));
|
|
|
|
// Check expected filenames
|
|
assert!(thinned_dir.ends_with("thinned"));
|
|
assert!(session_file.ends_with("session.json"));
|
|
assert!(summary_file.ends_with("context_summary.txt"));
|
|
assert!(todo_file.ends_with("todo.g3.md"));
|
|
}
|
|
}
|