#![allow(
    unused_imports,
    unused_variables,
    unused_mut,
    unreachable_code,
    dead_code
)]
//! Core workspace library: FS, VCS, permissions, tool config, and subsystem wiring.
pub mod activity;
pub mod capability;
pub mod channel;
pub mod config;
pub mod discovery;
pub mod envrc;
pub mod error;
pub mod file_system;
pub mod folder_trust;
pub mod foreign_sessions;
pub mod fs_notify;
pub mod handle;
pub mod permission;
pub mod project_config;
pub mod session;
pub mod status_config;
pub use status_config::StatusConfig;
pub mod trust;
pub mod util;
pub mod workspace_ops;
pub mod worktree;
pub use capability::CapabilityMode;
pub use channel::{TransportCallResult, TransportContext, TransportError, TransportNotification};
pub use config::{
    AgentSessionConfig, DEFAULT_EVENT_BUFFER_CAPACITY, HookSourceConfig, IsolationMode,
    MemoryConfig, SessionContextFactory, SessionTerminalBackend, WorkspaceConfig,
};
pub use error::{WorkspaceError, WorkspaceResult};
pub use file_system::*;
pub use handle::WorkspaceHandle;
pub use kigi_hunk_tracker::HunkTrackerHandle;
pub use kigi_workspace_types::WorkspaceEvent;
pub use permission::*;
pub use session::{WorkspaceSession, WorkspaceShared};
pub use session::{file_state, git, jj};
pub use workspace_ops::{WorkspaceOp, WorkspaceOps};
/// Zero-init every workspace metric family so idle panels render a `0` baseline
/// instead of "No data". Idempotent; call once at startup.
pub fn init_metrics() {
    handle::init_metrics();
    session::swap_policy::init_metrics();
}
/// Crate-wide lock serializing every test that mutates the process-global
/// environment (`KIGI_SHARE_DIR`, `HOME`, …). nextest isolates each test in its own
/// process, but `cargo test --lib` shares ONE process across threads, so
/// per-module locks don't serialize cross-module — a peer test in another module
/// can clobber `KIGI_SHARE_DIR` mid-test. A single shared lock (used by every
/// env-mutating test module) is required for that single-process run to be
/// race-free.
#[cfg(test)]
pub(crate) static ENV_TEST_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
/// Crate-shared RAII guard for a single process env var in tests: sets (or
/// unsets) it on construction and restores the prior value on drop. The ONE
/// generic env-var guard for the whole crate (replaces the per-module copies).
///
/// Hold it together with [`ENV_TEST_LOCK`] for the test's lifetime, acquiring
/// the lock FIRST so it drops LAST — the env restore (this guard) then runs
/// before the lock releases, so no peer test observes the temporary value.
#[cfg(test)]
pub(crate) struct TestEnvGuard {
    key: &'static str,
    prev: Option<std::ffi::OsString>,
}
#[cfg(test)]
impl TestEnvGuard {
    /// Set `key` to `val`, restoring the prior value on drop.
    pub(crate) fn set(key: &'static str, val: &std::path::Path) -> Self {
        let prev = std::env::var_os(key);
        unsafe { std::env::set_var(key, val) };
        Self { key, prev }
    }
    /// Unset `key`, restoring the prior value on drop.
    pub(crate) fn unset(key: &'static str) -> Self {
        let prev = std::env::var_os(key);
        unsafe { std::env::remove_var(key) };
        Self { key, prev }
    }
}
#[cfg(test)]
impl Drop for TestEnvGuard {
    fn drop(&mut self) {
        match self.prev.take() {
            Some(prev) => unsafe { std::env::set_var(self.key, prev) },
            None => unsafe { std::env::remove_var(self.key) },
        }
    }
}
/// Holds [`ENV_TEST_LOCK`] AND a set of [`TestEnvGuard`]s as ONE value, so a
/// test (or fixture) can return/bind it however it likes and still be correct.
///
/// Struct fields drop in DECLARATION order, so `_env` (declared first) restores
/// every env var BEFORE `_lock` (declared last) releases the lock — making the
/// "restore before unlock" invariant compile-enforced, not convention-dependent
/// (a single `let _ = LockedTestEnv::lock()…;` binding can't reorder it).
///
/// Acquire the lock first via [`lock`](Self::lock), then mutate env under it with
/// the chained [`set`](Self::set) builder.
#[cfg(test)]
pub(crate) struct LockedTestEnv {
    _env: Vec<TestEnvGuard>,
    _lock: std::sync::MutexGuard<'static, ()>,
}
#[cfg(test)]
impl LockedTestEnv {
    /// Acquire [`ENV_TEST_LOCK`] (held until this value drops).
    pub(crate) fn lock() -> Self {
        Self {
            _env: Vec::new(),
            _lock: ENV_TEST_LOCK.lock().unwrap_or_else(|e| e.into_inner()),
        }
    }
    /// Set `key` to `val` under the held lock, restoring the prior value on drop.
    ///
    /// Intended for DISTINCT keys; the restore order across repeated `set`s of
    /// the SAME key is unspecified (guards restore in insertion order).
    pub(crate) fn set(mut self, key: &'static str, val: &std::path::Path) -> Self {
        self._env.push(TestEnvGuard::set(key, val));
        self
    }
}
#[cfg(test)]
mod init_metrics_tests {
    /// `init_metrics()` is idempotent (a double call must not panic on
    /// re-register) and populates a `0` baseline series for each family so
    /// panels render `0` instead of "No data".
    #[test]
    fn init_metrics_is_idempotent_and_registers_baselines() {
        super::init_metrics();
        super::init_metrics();
        let families = prometheus::gather();
        let has = |name: &str, want: &[(&str, &str)]| {
            families
                .iter()
                .filter(|mf| mf.name() == name)
                .flat_map(|mf| mf.get_metric())
                .any(|m| {
                    want.iter().all(|(k, v)| {
                        m.get_label()
                            .iter()
                            .any(|l| l.name() == *k && l.value() == *v)
                    })
                })
        };
        assert!(has(
            "kigi_workspace_toolset_swap_rejected_total",
            &[("reason", "turn_active"), ("trigger", "update_tool_config")]
        ));
        assert!(has(
            "kigi_workspace_rewind_checkpoint_capture_total",
            &[("domain", "fs"), ("outcome", "completed")]
        ));
        assert!(
            families
                .iter()
                .any(|mf| mf.name() == "kigi_workspace_terminal_backend_orphaned_total")
        );
    }
}
