Skip to main content

lean_ctx/core/
activity.rs

1// SPDX-License-Identifier: Apache-2.0
2//! Facade of `lean-ctx-activity`: the per-session activity stream under
3//! `<data dir>/activity`, with this Instance's secret redaction. Producers
4//! (hooks, MCP calls, ACP client callbacks) call [`record`]; it never fails
5//! the caller.
6
7pub use lean_ctx_activity::*;
8
9/// The store of this Instance.
10pub fn store() -> Option<Store> {
11    crate::core::data_dir::lean_ctx_data_dir()
12        .ok()
13        .map(|dir| Store::new(dir.join("activity")))
14}
15
16/// The project root a stream is kept under: normalized and promoted to its
17/// git root, so a hook's `cwd` in a subdirectory, the MCP session's root and
18/// a reader's `--project-root` name the same project.
19pub fn project_root(path: &str) -> String {
20    crate::core::command_root::promote_to_git_root(
21        &crate::core::index_paths::normalize_project_root(path),
22    )
23}
24
25/// Record `draft` now: secrets masked (`core::redaction`, the shell's
26/// redaction), text bounded. Fail-open: an event that cannot be stored is
27/// dropped with a debug log.
28pub fn record(mut draft: Draft) {
29    let Some(store) = store() else {
30        return;
31    };
32    draft.project_root = project_root(&draft.project_root);
33    if let Err(error) = store.append(
34        draft,
35        chrono::Utc::now(),
36        &crate::core::redaction::redact_text,
37    ) {
38        tracing::debug!(%error, "lean-ctx: activity event dropped");
39    }
40}