Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub fn context_scout_backend_from_automation_config(
}
}

#[hotpath::measure(label = "agent_hosts.context_scout.model_route")]
pub fn context_scout_model_assistant_from_automation_config(
config: &AutomationConfig,
) -> Arc<dyn ContextScoutModelAssistantV1> {
Expand Down Expand Up @@ -166,6 +167,7 @@ fn scout_model_error_from_agent_task(error: AgentTaskError) -> ContextScoutModel
}
}

#[hotpath::measure(label = "agent_hosts.context_scout.model_request")]
fn backend_request(
request: ContextScoutModelRequestV1,
max_output_tokens: usize,
Expand Down Expand Up @@ -213,6 +215,7 @@ fn response_schema() -> Value {
})
}

#[hotpath::measure(label = "agent_hosts.context_scout.model_proposal")]
fn response_to_proposal(
response: AgentTaskResponse,
requested_backend: ContextScoutModelBackendV1,
Expand Down
1 change: 1 addition & 0 deletions crates/tracedecay-agent-hosts/src/hooks/cursor_compact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub async fn cursor_pre_compact_via_daemon(event_json: &str) -> CursorPreCompact
cursor_pre_compact_via_daemon_with_telemetry(event_json, None).await
}

#[hotpath::measure(future = true, label = "agent_hosts.hooks.cursor.compact_via_daemon")]
pub(super) async fn cursor_pre_compact_via_daemon_with_telemetry(
event_json: &str,
telemetry: Option<&super::analytics::HookTimingSpan>,
Expand Down
4 changes: 4 additions & 0 deletions crates/tracedecay-agent-hosts/src/hooks/daemon_ports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ pub(crate) fn now_utc() -> UtcMicros {
UtcMicros(micros.max(1))
}

#[hotpath::measure(label = "agent_hosts.hook_ports.admission_decode")]
pub(crate) fn daemon_admission_response(response: &serde_json::Value) -> DaemonAdmissionResponseV1 {
let unavailable = || DaemonAdmissionResponseV1 {
immediate: HookImmediateAdmissionV1::Unavailable,
Expand Down Expand Up @@ -218,6 +219,7 @@ fn delivery_outcome_from_status(status: Option<&str>) -> HookFeedbackDeliveryOut
}
}

#[hotpath::measure(future = true, label = "agent_hosts.hook_ports.timed_daemon_action")]
async fn timed_daemon_hook_action(
project_root: &Path,
action: serde_json::Value,
Expand Down Expand Up @@ -291,6 +293,7 @@ impl<'a> DaemonDeliveryReceiptPort<'a> {
Self { project_root }
}

#[hotpath::measure(future = true, label = "agent_hosts.hook_ports.post_receipt")]
pub(crate) async fn post_receipt(
&self,
receipt: &ContextScoutDeliveryReceiptV1,
Expand Down Expand Up @@ -411,6 +414,7 @@ impl<'a> DaemonOpenCodeLspUpdatePort<'a> {
}
}

#[hotpath::measure(future = true, label = "agent_hosts.hook_ports.opencode_lsp_submit")]
pub(crate) async fn submit_updated_event(&self, event: &serde_json::Value) -> bool {
let response = super::daemon_hook_action(
Some(self.project_root),
Expand Down
3 changes: 3 additions & 0 deletions crates/tracedecay-agent-hosts/src/hooks/kiro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const KIRO_HOT_INGEST_BUDGET: std::time::Duration = std::time::Duration::from_mi
/// Kiro `preToolUse` hook handler.
///
/// Blocks with exit code 2 and stderr, per Kiro's hook contract.
#[hotpath::measure(label = "agent_hosts.hooks.kiro.pre_tool_use")]
pub fn hook_kiro_pre_tool_use() -> i32 {
let event = read_hook_event!();
let parsed = serde_json::from_str::<Value>(&event).unwrap_or(Value::Null);
Expand Down Expand Up @@ -139,6 +140,7 @@ fn collect_strings<'a>(value: &'a Value, out: &mut Vec<&'a str>) {
///
/// Resets the per-turn counter, catches up transcripts, and injects bounded
/// user/project memory relevant to the submitted prompt.
#[hotpath::measure(future = true, label = "agent_hosts.hooks.kiro.prompt_submit")]
pub async fn hook_kiro_prompt_submit() -> i32 {
let event = read_hook_event!();
let parsed = serde_json::from_str::<Value>(&event).unwrap_or(Value::Null);
Expand Down Expand Up @@ -201,6 +203,7 @@ pub async fn hook_kiro_prompt_submit() -> i32 {
///
/// Notifies the daemon after Kiro writes. Missing daemon/index state is
/// fail-open.
#[hotpath::measure(future = true, label = "agent_hosts.hooks.kiro.post_tool_use")]
pub async fn hook_kiro_post_tool_use() -> i32 {
let event = read_hook_event!();
// One parse for the root, the analytics row, and the notification.
Expand Down
3 changes: 3 additions & 0 deletions crates/tracedecay-agent-hosts/src/hooks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ pub fn aggregate_hook_completed_readiness(rows: &[Value]) -> HookCompletedReadin
use tool_hints::{HintAgent, ToolHint};
use tracedecay_policy::hint_delivery::HintDeliveryDecisionV1;

#[hotpath::measure(future = true, label = "agent_hosts.hooks.dispatch_kimi_event")]
pub async fn dispatch_kimi_event(event_json: &str, project_root: &Path) -> Option<String> {
let telemetry = record_other_hook_invoked(Some(project_root), "kimi_event", event_json);
dispatch::dispatch(
Expand All @@ -98,6 +99,7 @@ pub async fn dispatch_kimi_event(event_json: &str, project_root: &Path) -> Optio
.flatten()
}

#[hotpath::measure(future = true, label = "agent_hosts.hooks.dispatch_opencode_event")]
pub async fn dispatch_opencode_event(event_json: &str, project_root: &Path) -> Option<String> {
let telemetry = record_other_hook_invoked(Some(project_root), "opencode_event", event_json);
let dispatch = if tracedecay_hooks::decode_opencode_lsp_event(event_json.as_bytes()).is_ok() {
Expand All @@ -114,6 +116,7 @@ pub async fn dispatch_opencode_event(event_json: &str, project_root: &Path) -> O
dispatch.into_recorded_guidance(&telemetry).flatten()
}

#[hotpath::measure(future = true, label = "agent_hosts.hooks.dispatch_opencode_tool_after")]
pub async fn dispatch_opencode_tool_after(event_json: &str, project_root: &Path) -> Option<String> {
let telemetry =
record_other_hook_invoked(Some(project_root), "opencode_tool_after", event_json);
Expand Down
18 changes: 18 additions & 0 deletions crates/tracedecay-agent-hosts/src/native_integration/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ impl DaemonNativeIntegrationStore {
}

/// Persists one issued approval commitment (approval issuance operation).
#[hotpath::measure(label = "agent_hosts.native_store.save_approval")]
pub(crate) fn save_approval(
&self,
approval: NativeIntegrationApprovalV1,
Expand All @@ -211,6 +212,7 @@ impl DaemonNativeIntegrationStore {
}

/// Reads one issued approval commitment for apply resolution.
#[hotpath::measure(label = "agent_hosts.native_store.read_approval")]
pub(crate) fn read_approval(
&self,
approval_id: &NativeIntegrationApprovalId,
Expand Down Expand Up @@ -247,6 +249,7 @@ impl Drop for DaemonNativeIntegrationStore {
}

impl NativeIntegrationStore for DaemonNativeIntegrationStore {
#[hotpath::measure(label = "agent_hosts.native_store.save_preview")]
fn save_preview(
&self,
preview: NativeIntegrationPreviewV1,
Expand All @@ -256,6 +259,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.read_preview")]
fn read_preview(
&self,
preview_id: &NativeIntegrationPreviewId,
Expand All @@ -265,6 +269,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.begin_or_replay")]
fn begin_or_replay(
&self,
record: NativeIntegrationRecordV1,
Expand All @@ -274,6 +279,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.read_status")]
fn read_status(
&self,
transaction_id: &NativeIntegrationTransactionId,
Expand All @@ -283,6 +289,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.read_record")]
fn read_record(
&self,
transaction_id: &NativeIntegrationTransactionId,
Expand All @@ -292,6 +299,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.read_receipt")]
fn read_receipt(
&self,
transaction_id: &NativeIntegrationTransactionId,
Expand All @@ -301,6 +309,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.compare_and_swap_status")]
fn compare_and_swap_status(
&self,
transaction_id: &NativeIntegrationTransactionId,
Expand All @@ -317,6 +326,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.write_terminal")]
fn write_terminal(
&self,
transaction_id: &NativeIntegrationTransactionId,
Expand All @@ -333,6 +343,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.pending_transactions")]
fn pending_transactions(
&self,
repository_id: Option<&RepositoryId>,
Expand All @@ -345,6 +356,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.approval_consumed")]
fn approval_consumed(
&self,
approval_id: &NativeIntegrationApprovalId,
Expand All @@ -354,6 +366,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.quarantine_repository")]
fn quarantine_repository(
&self,
repository_id: &RepositoryId,
Expand All @@ -368,6 +381,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.begin_worktree_cleanup")]
fn begin_worktree_cleanup(
&self,
transaction: NativeWorktreeCleanupTransactionV1,
Expand All @@ -380,6 +394,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.read_worktree_cleanup")]
fn read_worktree_cleanup(
&self,
confirmation_digest: &ManifestDigest,
Expand All @@ -392,6 +407,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.pending_worktree_cleanups")]
fn pending_worktree_cleanups(
&self,
repository_id: &RepositoryId,
Expand All @@ -406,6 +422,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.compare_and_swap_worktree_cleanup")]
fn compare_and_swap_worktree_cleanup(
&self,
confirmation_digest: &ManifestDigest,
Expand All @@ -422,6 +439,7 @@ impl NativeIntegrationStore for DaemonNativeIntegrationStore {
Self::await_reply(&receiver)
}

#[hotpath::measure(label = "agent_hosts.native_store.write_worktree_cleanup_terminal")]
fn write_worktree_cleanup_terminal(
&self,
confirmation_digest: &ManifestDigest,
Expand Down
6 changes: 6 additions & 0 deletions crates/tracedecay-agent-hosts/src/ports/hook_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ pub fn register_cursor_catch_up_ingest_max_bytes(max_bytes: CursorCatchUpIngestM
/// Errors when the root never registered an invoker. Callers already treat a
/// daemon request failure as "defer this work and warn", which is the correct
/// handling for an unwired build too.
#[hotpath::measure(future = true, label = "agent_hosts.hook_runtime.daemon_tool")]
pub async fn daemon_tool_json(
project_root: Option<&Path>,
tool_name: &str,
Expand All @@ -137,11 +138,13 @@ pub async fn daemon_tool_json(
invoker(project_root, tool_name, arguments, require_project_identity).await
}

#[hotpath::measure(future = true, label = "agent_hosts.hook_runtime.resolve_root")]
pub async fn resolve_project_root_with_identity(start: &Path) -> Option<PathBuf> {
let resolver = PROJECT_ROOT_RESOLVER.get()?;
resolver(start).await
}

#[hotpath::measure(label = "agent_hosts.hook_runtime.resolve_scope")]
pub fn resolve_hook_scope(
project_root: &Path,
project_id: &ProjectId,
Expand All @@ -152,6 +155,7 @@ pub fn resolve_hook_scope(
)
}

#[hotpath::measure(future = true, label = "agent_hosts.hook_runtime.notify_event")]
pub async fn notify_hook_event(project_root: &Path, event: DaemonHookEvent) {
if let Some(notifier) = HOOK_EVENT_NOTIFIER.get() {
notifier(project_root, event).await;
Expand All @@ -164,6 +168,7 @@ pub fn hook_timings_enabled(project_root: &Path) -> Option<bool> {
}

#[must_use]
#[hotpath::measure(label = "agent_hosts.hook_runtime.project_initialized")]
pub fn is_project_initialized(project_root: &Path) -> bool {
PROJECT_INITIALIZATION_GATE.get().map_or_else(
|| {
Expand All @@ -174,6 +179,7 @@ pub fn is_project_initialized(project_root: &Path) -> bool {
)
}

#[hotpath::measure(future = true, label = "agent_hosts.hook_runtime.store_layout")]
pub async fn resolve_store_layout(project_root: &Path) -> Result<StoreLayout> {
let Some(resolver) = STORE_LAYOUT_RESOLVER.get() else {
return Err(TraceDecayError::Config {
Expand Down
Loading