wsb 0.88.382266

Workspace - A tool suite for file operations, version management, and development workflow automation
Documentation
diff --git a/src/state/state_common.rs b/src/state/state_common.rs
index ab1bbb7..4414544 100644
--- a/src/state/state_common.rs
+++ b/src/state/state_common.rs
@@ -2,6 +2,7 @@ use anyhow::{Context, Result};
 use log;
 use regex::Regex;
 use serde::{Deserialize, Serialize};
+use sqlx::Row;
 use std::fs;
 use std::path::{Path, PathBuf};
 use std::process::Command;
@@ -67,6 +68,38 @@ impl StateConfig {
     }
 }
 
+pub fn calculate_workspace_version(repo_root: &Path) -> Result<VersionInfo> {
+    if tokio::runtime::Handle::try_current().is_ok() {
+        anyhow::bail!(
+            "calculate_workspace_version cannot be called from an async runtime; use calculate_workspace_version_async"
+        );
+    }
+    let rt = tokio::runtime::Runtime::new()?;
+    rt.block_on(calculate_workspace_version_async(repo_root))
+}
+
+pub async fn calculate_workspace_version_async(repo_root: &Path) -> Result<VersionInfo> {
+    let major_version = load_project_major_version_async(repo_root).await?;
+    VersionInfo::calculate_with_major(major_version)
+}
+
+async fn load_project_major_version_async(repo_root: &Path) -> Result<u32> {
+    let db_path = repo_root.join(".wsb/project.db");
+    if let Some(parent) = db_path.parent() {
+        fs::create_dir_all(parent)?;
+    }
+    load_state_config_from_db(&db_path).await?;
+    let database_url = format!("sqlite:{}", db_path.display());
+    let pool = sqlx::SqlitePool::connect(&database_url).await?;
+    let row = sqlx::query("SELECT major_version FROM projects LIMIT 1")
+        .fetch_optional(&pool)
+        .await?;
+
+    Ok(row
+        .map(|row| row.get::<i64, _>("major_version") as u32)
+        .unwrap_or(0))
+}
+
 #[derive(Debug, Clone)]
 pub struct VersionInfo {
     pub major_version: String,
@@ -840,6 +873,10 @@ fn update_julia_project(content: &str, version: &str) -> Result<String> {
 // Database integration functions for StateConfig
 async fn load_state_config_from_db(db_path: &std::path::Path) -> Result<StateConfig> {
     use sqlx::{SqlitePool, migrate::MigrateDatabase, Row};
+
+    if let Some(parent) = db_path.parent() {
+        fs::create_dir_all(parent)?;
+    }
     
     // Ensure database exists and is initialized
     let database_url = format!("sqlite:{}", db_path.display());
@@ -1354,6 +1391,46 @@ set(CMAKE_CXX_STANDARD 17)
         assert_eq!(content.trim(), "1.0.5.100");
     }
 
+    fn run_git(repo_root: &Path, args: &[&str]) {
+        let status = Command::new("git")
+            .args(args)
+            .current_dir(repo_root)
+            .status()
+            .unwrap();
+        assert!(status.success(), "git command failed: {:?}", args);
+    }
+
+    #[tokio::test]
+    async fn test_calculate_workspace_version_uses_project_major_version_from_db() {
+        let temp_dir = TempDir::new().unwrap();
+        let repo_root = temp_dir.path();
+
+        run_git(repo_root, &["init"]);
+        run_git(repo_root, &["config", "user.name", "Test User"]);
+        run_git(repo_root, &["config", "user.email", "test@example.com"]);
+
+        fs::write(repo_root.join("README.md"), "hello\n").unwrap();
+        run_git(repo_root, &["add", "README.md"]);
+        run_git(repo_root, &["commit", "-m", "initial"]);
+
+        let _ = StateConfig::load_async(repo_root).await.unwrap();
+        let db_path = repo_root.join(".wsb/project.db");
+        let database_url = format!("sqlite:{}", db_path.display());
+        let pool = sqlx::SqlitePool::connect(&database_url).await.unwrap();
+        sqlx::query("UPDATE projects SET major_version = 7 WHERE id = (SELECT id FROM projects LIMIT 1)")
+            .execute(&pool)
+            .await
+            .unwrap();
+
+        let expected = VersionInfo::calculate_with_major(7).unwrap();
+        let actual = calculate_workspace_version_async(repo_root)
+            .await
+            .unwrap();
+
+        assert_eq!(actual.major_version, "v7");
+        assert_eq!(actual.full_version, expected.full_version);
+    }
+
     #[test]
     fn test_update_build_gradle_kts() {
         let content = r#"plugins {