pub trait KindHook:
Send
+ Sync
+ Debug {
// Required methods
fn prepare_create<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
runtime: &'life1 KhiveRuntime,
args: &'life2 mut Value,
) -> Pin<Box<dyn Future<Output = Result<(), RuntimeError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn after_create<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
runtime: &'life1 KhiveRuntime,
id: Uuid,
args: &'life2 Value,
) -> Pin<Box<dyn Future<Output = Result<(), RuntimeError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
}Expand description
Per-kind specialization for shared CRUD (ADR-030).
Packs implement KindHook for kinds they own that need:
- Defaults filled into create args (e.g.
status="inbox"for tasks) - Derived properties computed from args (e.g. salience from priority)
- Side-effect writes after the storage commit (e.g.
depends_onedges)
Hooks are stateless from the framework’s perspective — they receive the
runtime as a method parameter and operate on the args Value directly.
The pack registers them via PackRuntime::kind_hook.
Lifecycle verbs (e.g. gtd’s complete, transition) remain pack-owned
verbs and do not flow through this trait — only the create path does.
Required Methods§
Sourcefn prepare_create<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
runtime: &'life1 KhiveRuntime,
args: &'life2 mut Value,
) -> Pin<Box<dyn Future<Output = Result<(), RuntimeError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn prepare_create<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
runtime: &'life1 KhiveRuntime,
args: &'life2 mut Value,
) -> Pin<Box<dyn Future<Output = Result<(), RuntimeError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Mutate args before the storage write. Fill defaults, normalize values, rearrange user-facing fields into the storage shape expected by the shared CRUD handler.
Returning an error aborts the create call (no storage write happens).
Sourcefn after_create<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
runtime: &'life1 KhiveRuntime,
id: Uuid,
args: &'life2 Value,
) -> Pin<Box<dyn Future<Output = Result<(), RuntimeError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn after_create<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
runtime: &'life1 KhiveRuntime,
id: Uuid,
args: &'life2 Value,
) -> Pin<Box<dyn Future<Output = Result<(), RuntimeError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Fire side effects after a successful storage write — graph edges, derived observations, etc. The newly created record’s UUID is passed so the hook can attach metadata referencing it.
Errors here are logged but not propagated — the storage write has
already succeeded; failing the call would mislead the caller.
Implementations should tracing::warn! and return Ok(()) for
best-effort side effects.