Skip to main content

KindHook

Trait KindHook 

Source
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_on edges)

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§

Source

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).

Source

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.

Implementors§