Skip to main content

ai_memory/hooks/
mod.rs

1// Copyright 2026 AlphaOne LLC
2// SPDX-License-Identifier: Apache-2.0
3//
4// v0.7 Track G — programmable lifecycle hook pipeline.
5//
6// This module is the substrate for tasks G1-G11 of the
7// `attested-cortex` epic. G1 lands the configuration schema
8// (`hooks.toml`) and the SIGHUP-driven hot-reload plumbing.
9// Subsequent tasks layer on:
10//
11//   * G2  — full payload structs for the 20 lifecycle events.
12//   * G3  — subprocess executor (exec + daemon modes).
13//   * G4  — `HookDecision` contract.
14//   * G5  — chain ordering with first-deny-wins short-circuit.
15//   * G6  — per-event-class deadlines.
16//   * G7+ — actual firing at the memory operation points.
17//
18// G1 deliberately ships *only* the schema + loader + hot-reload
19// signal handler. It does not fire hooks, validate command paths
20// against a sandbox, or implement the executor. Those land in
21// follow-up PRs on this same `feat/v0.7-g-*` track.
22
23pub mod chain;
24pub mod config;
25pub mod decision;
26pub mod events;
27pub mod executor;
28// G10 — recall hot-path helper. Wraps `HookChain::fire` with the
29// `PreRecallExpand` payload-marshalling so `mcp::handle_recall`
30// stays a one-liner at the fire site.
31pub mod recall;
32pub mod timeouts;
33// v0.7.0 QW-1 — `post_reflect` substrate-side hook plug-ins (file-
34// backed auto-export, future post-commit notifications). These are
35// distinct from the cross-process `HookEvent::PostReflect` family in
36// `events.rs` — those serialise across subprocess boundaries; this
37// module is in-substrate (`std::thread::spawn` + the rusqlite
38// connection on the worker thread).
39pub mod post_reflect;
40
41// v0.7.0 WT-1-D — `pre_store` substrate-side hook plug-ins
42// (auto-atomisation deferred-enqueue, future pre-commit observers).
43// Same in-substrate discipline as `post_reflect` — distinct from the
44// cross-process `HookEvent::PreStore` family in `events.rs`.
45pub mod pre_store;
46
47// G2 lifted `HookEvent` out of `config.rs` into `events.rs` and
48// attached payload structs to every variant. The re-export keeps
49// G1's `use crate::hooks::HookEvent` (and the
50// `crate::hooks::config::HookEvent` compatibility alias) resolving.
51pub use chain::{
52    AskUserPrompt, ChainResult, HookChain, fire_on_index_eviction, spawn_eviction_observer,
53};
54pub use config::{FailMode, HookConfig, HookMode, HooksConfigError};
55pub use events::{EvictionEvent, HookEvent};
56// G4 — full HookDecision contract. G3 shipped a local `Allow +
57// Deny` prototype inside `executor.rs`; G4 lifts the type into
58// `decision.rs` with the four-variant epic spec (Allow / Modify /
59// Deny / AskUser) and a strict JSON wire contract. The re-export
60// here keeps G3 call sites (`use crate::hooks::HookDecision`,
61// `use crate::hooks::executor::HookDecision`) resolving via the
62// canonical `crate::hooks::decision::HookDecision` path.
63pub use decision::{DecisionParseError, HookDecision, ModifyPayload, is_pre_event};
64// G3 — subprocess hook executor. Re-exports keep call sites
65// (`use crate::hooks::HookExecutor`) tidy without requiring every
66// caller to know the `executor::` submodule path.
67pub use executor::{
68    DaemonExecutor, ExecExecutor, ExecutorError, ExecutorMetrics, ExecutorRegistry, HookExecutor,
69};
70// G6 — per-event-class hard timeouts. Re-exports the budget table
71// + violation counter so the doctor surface and the chain runner
72// can both reach for the canonical type without a deeper import.
73pub use timeouts::{
74    EventClass, HOT_PATH_CLASS_DEADLINE_MS, INDEX_CLASS_DEADLINE_MS, READ_CLASS_DEADLINE_MS,
75    TRANSCRIPT_CLASS_DEADLINE_MS, WRITE_CLASS_DEADLINE_MS, class_deadline,
76    class_deadline_for_event, event_class, per_hook_budget_ms, record_timeout_violation,
77    timeout_violations_total,
78};
79// G10 — pre_recall_expand hot-path helper.
80pub use recall::{PreRecallOutcome, apply_pre_recall_expand};