Remove legacy logs/ directory, consolidate all data under .g3/
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
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -129,8 +129,7 @@ impl ErrorContext {
|
||||
return;
|
||||
}
|
||||
|
||||
let base_logs_dir = crate::logs_dir();
|
||||
let logs_dir = base_logs_dir.join("errors");
|
||||
let logs_dir = crate::paths::get_errors_dir();
|
||||
if !logs_dir.exists() {
|
||||
if let Err(e) = std::fs::create_dir_all(&logs_dir) {
|
||||
error!("Failed to create error logs directory: {}", e);
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
//!
|
||||
//! Used by both autonomous mode (g3-cli) and planning mode (g3-planner).
|
||||
|
||||
use crate::{logs_dir, Agent, TaskResult};
|
||||
use crate::{Agent, TaskResult};
|
||||
use crate::ui_writer::UiWriter;
|
||||
use serde_json::Value;
|
||||
use std::path::PathBuf;
|
||||
use tracing::{debug, warn};
|
||||
|
||||
/// Result of feedback extraction with source information
|
||||
@@ -60,8 +59,6 @@ impl ExtractedFeedback {
|
||||
pub struct FeedbackExtractionConfig {
|
||||
/// Whether to print debug information
|
||||
pub verbose: bool,
|
||||
/// Custom logs directory (overrides default)
|
||||
pub logs_dir: Option<PathBuf>,
|
||||
/// Default feedback message if extraction fails
|
||||
pub default_feedback: String,
|
||||
}
|
||||
@@ -70,7 +67,6 @@ impl Default for FeedbackExtractionConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
verbose: false,
|
||||
logs_dir: None,
|
||||
default_feedback: "The implementation needs review. Please ensure all requirements are met and the code compiles without errors.".to_string(),
|
||||
}
|
||||
}
|
||||
@@ -149,17 +145,10 @@ fn try_extract_last_assistant_message(
|
||||
session_id: &str,
|
||||
config: &FeedbackExtractionConfig,
|
||||
) -> Option<String> {
|
||||
// Try new .g3/sessions/<session_id>/session.json path first
|
||||
let log_file_path = crate::get_session_file(session_id);
|
||||
let _ = config; // config no longer used but kept for API compatibility
|
||||
|
||||
// Fall back to old logs/ path if new path doesn't exist
|
||||
let log_file_path = if log_file_path.exists() {
|
||||
log_file_path
|
||||
} else {
|
||||
let logs_path = config.logs_dir.clone().unwrap_or_else(logs_dir);
|
||||
logs_path.join(format!("g3_session_{}.json", session_id))
|
||||
};
|
||||
|
||||
// Use .g3/sessions/<session_id>/session.json path
|
||||
let log_file_path = crate::get_session_file(session_id);
|
||||
if !log_file_path.exists() {
|
||||
debug!("Session log file not found: {:?}", log_file_path);
|
||||
return None;
|
||||
@@ -214,17 +203,10 @@ fn try_extract_from_session_log(
|
||||
session_id: &str,
|
||||
config: &FeedbackExtractionConfig,
|
||||
) -> Option<String> {
|
||||
// Try new .g3/sessions/<session_id>/session.json path first
|
||||
let log_file_path = crate::get_session_file(session_id);
|
||||
let _ = config; // config no longer used but kept for API compatibility
|
||||
|
||||
// Fall back to old logs/ path if new path doesn't exist
|
||||
let log_file_path = if log_file_path.exists() {
|
||||
log_file_path
|
||||
} else {
|
||||
let logs_path = config.logs_dir.clone().unwrap_or_else(logs_dir);
|
||||
logs_path.join(format!("g3_session_{}.json", session_id))
|
||||
};
|
||||
|
||||
// Use .g3/sessions/<session_id>/session.json path
|
||||
let log_file_path = crate::get_session_file(session_id);
|
||||
if !log_file_path.exists() {
|
||||
debug!("Session log file not found: {:?}", log_file_path);
|
||||
return None;
|
||||
@@ -358,17 +340,10 @@ fn try_extract_from_conversation_history(
|
||||
session_id: &str,
|
||||
config: &FeedbackExtractionConfig,
|
||||
) -> Option<String> {
|
||||
// Try new .g3/sessions/<session_id>/session.json path first
|
||||
let log_file_path = crate::get_session_file(session_id);
|
||||
let _ = config; // config no longer used but kept for API compatibility
|
||||
|
||||
// Fall back to old logs/ path if new path doesn't exist
|
||||
let log_file_path = if log_file_path.exists() {
|
||||
log_file_path
|
||||
} else {
|
||||
let logs_path = config.logs_dir.clone().unwrap_or_else(logs_dir);
|
||||
logs_path.join(format!("g3_session_{}.json", session_id))
|
||||
};
|
||||
|
||||
// Use .g3/sessions/<session_id>/session.json path
|
||||
let log_file_path = crate::get_session_file(session_id);
|
||||
if !log_file_path.exists() {
|
||||
return None;
|
||||
}
|
||||
@@ -652,7 +627,6 @@ mod tests {
|
||||
fn test_feedback_extraction_config_default() {
|
||||
let config = FeedbackExtractionConfig::default();
|
||||
assert!(!config.verbose);
|
||||
assert!(config.logs_dir.is_none());
|
||||
assert!(config.default_feedback.contains("review"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,10 +53,11 @@ use std::time::{Duration, Instant};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::{debug, error, warn};
|
||||
|
||||
// Re-export path utilities for backward compatibility
|
||||
// Re-export path utilities
|
||||
pub use paths::{
|
||||
G3_WORKSPACE_PATH_ENV, ensure_session_dir, get_context_summary_file, get_g3_dir, get_logs_dir,
|
||||
get_session_file, get_session_logs_dir, get_session_todo_path, get_thinned_dir, logs_dir,
|
||||
G3_WORKSPACE_PATH_ENV, ensure_session_dir, get_context_summary_file, get_g3_dir,
|
||||
get_session_file, get_session_logs_dir, get_session_todo_path, get_thinned_dir,
|
||||
get_errors_dir, get_background_processes_dir, get_discovery_dir,
|
||||
};
|
||||
use paths::get_todo_path;
|
||||
|
||||
@@ -291,7 +292,7 @@ impl<W: UiWriter> Agent<W> {
|
||||
working_dir: None,
|
||||
background_process_manager: std::sync::Arc::new(
|
||||
background_process::BackgroundProcessManager::new(
|
||||
paths::get_logs_dir().join("background_processes")
|
||||
paths::get_background_processes_dir()
|
||||
)),
|
||||
pending_images: Vec::new(),
|
||||
is_agent_mode: false,
|
||||
|
||||
+22
-15
@@ -1,8 +1,8 @@
|
||||
//! Path utilities for G3 session and workspace management.
|
||||
//!
|
||||
//! This module centralizes all path-related logic for:
|
||||
//! - TODO file location
|
||||
//! - Logs directory
|
||||
//! - TODO file location
|
||||
//! - Error logs directory
|
||||
//! - Session directories and files
|
||||
//! - Thinned content storage
|
||||
|
||||
@@ -33,22 +33,29 @@ 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 logs directory.
|
||||
/// Get the path to the errors directory.
|
||||
///
|
||||
/// Checks for G3_WORKSPACE_PATH environment variable first (used by planning mode),
|
||||
/// then falls back to "logs" in the current directory.
|
||||
pub fn get_logs_dir() -> PathBuf {
|
||||
if let Ok(workspace_path) = std::env::var(G3_WORKSPACE_PATH_ENV) {
|
||||
PathBuf::from(workspace_path).join("logs")
|
||||
} else {
|
||||
std::env::current_dir().unwrap_or_default().join("logs")
|
||||
}
|
||||
/// Returns `.g3/errors/` in the workspace or current directory.
|
||||
pub fn get_errors_dir() -> PathBuf {
|
||||
get_g3_dir().join("errors")
|
||||
}
|
||||
|
||||
/// Public accessor for the logs directory path (for use by submodules).
|
||||
/// Alias for `get_logs_dir()` for backward compatibility.
|
||||
pub fn logs_dir() -> PathBuf {
|
||||
get_logs_dir()
|
||||
/// 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.
|
||||
|
||||
@@ -127,18 +127,4 @@ impl Project {
|
||||
std::env::set_current_dir(&self.workspace_dir)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get the logs directory for the project
|
||||
pub fn logs_dir(&self) -> PathBuf {
|
||||
self.workspace_dir.join("logs")
|
||||
}
|
||||
|
||||
/// Ensure the logs directory exists
|
||||
pub fn ensure_logs_dir(&self) -> Result<()> {
|
||||
let logs_dir = self.logs_dir();
|
||||
if !logs_dir.exists() {
|
||||
std::fs::create_dir_all(&logs_dir)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//! operations from the Agent, keeping the Agent as a thin orchestrator.
|
||||
|
||||
use crate::context_window::ContextWindow;
|
||||
use crate::paths::{ensure_session_dir, get_context_summary_file, get_g3_dir, get_logs_dir, get_session_file};
|
||||
use crate::paths::{ensure_session_dir, get_context_summary_file, get_g3_dir, get_session_file};
|
||||
use g3_providers::MessageRole;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
@@ -90,7 +90,7 @@ pub fn generate_session_id(description: &str, agent_name: Option<&str>) -> Strin
|
||||
/// Save the context window to a session file.
|
||||
///
|
||||
/// If session_id is provided, saves to `.g3/sessions/<session_id>/session.json`.
|
||||
/// Otherwise, falls back to `logs/g3_context_<timestamp>.json`.
|
||||
/// Otherwise, saves to `.g3/sessions/anonymous_<timestamp>/session.json`.
|
||||
pub fn save_context_window(
|
||||
session_id: Option<&str>,
|
||||
context_window: &ContextWindow,
|
||||
@@ -110,13 +110,13 @@ pub fn save_context_window(
|
||||
}
|
||||
get_session_file(id)
|
||||
} else {
|
||||
// Fallback to old logs/ directory for sessions without ID
|
||||
let logs_dir = get_logs_dir();
|
||||
if let Err(e) = std::fs::create_dir_all(&logs_dir) {
|
||||
error!("Failed to create logs directory: {}", e);
|
||||
// Create anonymous session for sessions without ID
|
||||
let anonymous_id = format!("anonymous_{}", timestamp);
|
||||
if let Err(e) = ensure_session_dir(&anonymous_id) {
|
||||
error!("Failed to create anonymous session directory: {}", e);
|
||||
return;
|
||||
}
|
||||
logs_dir.join(format!("g3_context_{}.json", timestamp))
|
||||
get_session_file(&anonymous_id)
|
||||
};
|
||||
|
||||
let context_data = serde_json::json!({
|
||||
@@ -252,8 +252,8 @@ pub fn log_error_to_session(
|
||||
.unwrap_or_default()
|
||||
.as_secs();
|
||||
|
||||
let logs_dir = get_logs_dir();
|
||||
let filename = logs_dir.join(format!("g3_session_{}.json", session_id));
|
||||
// Use the new .g3/sessions/<session_id>/session.json path
|
||||
let filename = get_session_file(session_id);
|
||||
|
||||
// Read existing session log
|
||||
let mut session_data: serde_json::Value = if filename.exists() {
|
||||
|
||||
@@ -29,7 +29,7 @@ echo "Done!"
|
||||
fs::set_permissions(&script_path, fs::Permissions::from_mode(0o755)).unwrap();
|
||||
}
|
||||
|
||||
let log_dir = test_dir.join("logs");
|
||||
let log_dir = test_dir.join(".g3").join("background_processes");
|
||||
let manager = BackgroundProcessManager::new(log_dir);
|
||||
|
||||
println!("\n=== Background Process Demo ===");
|
||||
|
||||
@@ -53,7 +53,7 @@ done
|
||||
fs::set_permissions(&script_path, fs::Permissions::from_mode(0o755)).unwrap();
|
||||
}
|
||||
|
||||
let log_dir = test_dir.join("logs");
|
||||
let log_dir = test_dir.join(".g3").join("background_processes");
|
||||
let manager = BackgroundProcessManager::new(log_dir);
|
||||
|
||||
// Start the process
|
||||
@@ -116,7 +116,7 @@ sleep 30
|
||||
fs::set_permissions(&script_path, fs::Permissions::from_mode(0o755)).unwrap();
|
||||
}
|
||||
|
||||
let log_dir = test_dir.join("logs");
|
||||
let log_dir = test_dir.join(".g3").join("background_processes");
|
||||
let manager = BackgroundProcessManager::new(log_dir);
|
||||
|
||||
// Start a process
|
||||
@@ -151,7 +151,7 @@ sleep 30
|
||||
let _ = fs::remove_dir_all(&test_dir);
|
||||
fs::create_dir_all(&test_dir).unwrap();
|
||||
|
||||
let log_dir = test_dir.join("logs");
|
||||
let log_dir = test_dir.join(".g3").join("background_processes");
|
||||
let manager = BackgroundProcessManager::new(log_dir);
|
||||
|
||||
// Getting a process that doesn't exist should return None
|
||||
|
||||
@@ -91,7 +91,7 @@ fn test_save_and_load_continuation() {
|
||||
"save_load_test".to_string(),
|
||||
None,
|
||||
Some("Test summary content".to_string()),
|
||||
"/logs/g3_session_save_load_test.json".to_string(),
|
||||
"/.g3/sessions/save_load_test/session.json".to_string(),
|
||||
35.5,
|
||||
Some("- [ ] Pending task".to_string()),
|
||||
temp_dir.path().to_string_lossy().to_string(),
|
||||
@@ -321,9 +321,9 @@ fn test_has_valid_continuation_with_existing_session_log() {
|
||||
let (temp_dir, original_dir) = setup_test_env();
|
||||
|
||||
// Create a fake session log file
|
||||
let logs_dir = temp_dir.path().join("logs");
|
||||
fs::create_dir_all(&logs_dir).expect("Failed to create logs dir");
|
||||
let session_log_path = logs_dir.join("g3_session_valid_test.json");
|
||||
let session_dir = temp_dir.path().join(".g3").join("sessions").join("valid_test");
|
||||
fs::create_dir_all(&session_dir).expect("Failed to create session dir");
|
||||
let session_log_path = session_dir.join("session.json");
|
||||
fs::write(&session_log_path, "{}").expect("Failed to write session log");
|
||||
|
||||
// Create a continuation pointing to the existing session log
|
||||
|
||||
Reference in New Issue
Block a user