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}