Expand description
ADR-099: the per-verb async prepare pass for the KG-substrate v1
admissible verbs (update, delete, link, merge), plus
prepare_add_entity/prepare_add_note for the ADR-046 proposal
changeset AddEntity/AddNote arms. Each prepare_* function reads
current state (async, outside any transaction) and returns a plain-data
crate::atomic_runner::AtomicOpPlan (crate::atomic_plan) for the
synchronous commit pass (crate::atomic_runner::run_atomic_unit) to
apply.
gtd.transition/gtd.complete prepare is deliberately not here (lives in
kkernel instead), and propose/review/withdraw/merge are on the
v1 admissible list but have no working prepare implementation in this
module (prepare_governance_unimplemented fails loudly rather than
silently no-opping; prepare_merge is unreachable through --atomic and
kept only for its own tests and as defense in depth). See
docs/api/atomic_prepare.md#scope-what-is-excluded-and-why for why each of these is excluded
and what would be required to admit them.
Structs§
- Post
Commit Effects Report - Everything one committed unit’s post-commit pass produced. A failing effect never discards the outcomes of the effects that completed, so callers can still disclose their model failures and truncation advisories.
- Post
Commit Embedding Outcome - Metadata produced by a reindex effect whose fail-closed stages succeeded.
- Reindex
Model Failure - An eligible-model failure after the note and its lexical index committed.
Enums§
- Atomic
Delete Kind - Caller-supplied delete-kind expectation, resolved via the canonical
resolve_kind_specat the kkernel--atomicseam.khive-runtimemust not depend onkhive-pack-kg(packs depend on the runtime, not the other way around), so this is a plain substrate-level shape rather thankhive_pack_kg::handlers::KindSpecitself: the kkernel seam does the pack-awareresolve_kind_specresolution (which needs aVerbRegistry, unreachable from this crate) and passes down only whatprepare_deleteneeds to enforce the mismatch check. - Atomic
Update Kind - Caller-supplied update-kind expectation, resolved via the canonical
resolve_kind_specat the kkernel--atomicseam: the same patternAtomicDeleteKinduses. Without this check,update(kind="document", id=<concept>)would be canonicallyNotFoundbut the atomic path would ignore the explicit kind and mutate the resolved entity anyway.khive-runtimemust not depend onkhive-pack-kg, so this is a plain substrate-level shape rather thankhive_pack_kg::handlers::KindSpecitself: the kkernel seam does the pack-aware resolution and passes down only whatprepare_updateneeds to enforce the mismatch check. - Reindex
Model Stage - The eligible-model stage that prevented a note’s vector refresh.
Functions§
- apply_
post_ commit_ effects - Run every deferred
PostCommitEffectafter a committed atomic unit. - apply_
post_ commit_ effects_ with_ failures - Failure-preserving form of
super::apply_post_commit_effects_with_report. Runs every effect, collecting the outcomes of those that completed and the error of each that did not, instead of replacing the outcomes with the first failure. - apply_
post_ commit_ effects_ with_ report - Embedding-reporting form of
apply_post_commit_effects. Re-fetches each target’s now-committed row outside any transaction and reuses the existingreindex_entity/reindex_note(FTS + embedding, same as the non-atomic path) for exact parity. Returns the typed embedding outcome for each reindex effect so callers can preserve truncation advisories and partial model failures instead of discarding them after commit. Model failures remain best-effort; lexical indexing and excluded-model cleanup errors propagate. When any effect fails, the other effects’ outcomes are dropped with the returned error;apply_post_commit_effects_with_failureskeeps both. - prepare_
add_ entity - Build the prepared plan for an
AddEntityproposal change. The entity row and FTS document are committed together; vector indexing is deferred until after commit because embedding may suspend.kindmust already be canonicalized by the caller because pack-aware resolution requires aVerbRegistry. - prepare_
add_ note - Build the prepared plan for an
AddNoteproposal change. Mirrorsprepare_add_entity’s shape and the samekind-already-canonicalized split.annotatesis out of scope: the proposalNoteDraftthis backs carries no annotates targets, unlikeKhiveRuntime::create_note’s general-purpose signature. - prepare_
delete expected_kind:Nonewhen the caller omittedkind(no check, parity with canonical’s own optional discriminator);Some(_)enforces an exact-parity mismatch check against the resolved record’s actual substrate/specific kind, mirroringhandle_delete’sentity.kind != *expected/note.kind != *expectedchecks.- prepare_
op - Build the prepared
AtomicOpPlanfor one KG-substrate admissible op (update,delete,link,merge). Returns a loudRuntimeErrorforpropose/review/withdraw(known scope gap, see module doc) and any other verb (the CLI boundary must reject those before calling this — a verb reaching here is either KG-substrate-admissible or a bug upstream). - prepare_
update expected_kind:Nonewhen the caller omittedkind(no check, parity with canonical’s own optional discriminator);Some(_)enforces an exact-parity mismatch check against the resolved record’s actual substrate/specific kind, mirroringhandle_update’sentity.kind != *k/ note kind checks (update.rs:200-201, :229-234). Task notes must pass the GTD pack hook before this orprepare_op("update", ..); neither runs it.- prepare_
update_ entity_ plan - Build an entity update plan from a typed patch. Proposal changesets use
this entry point so their explicit
description: nullclear operation is preserved instead of being collapsed by raw verb deserialization. - prepare_
update_ from_ note_ snapshot - Build an atomic update plan from the exact note snapshot already supplied
to a pack update hook. Persistence is guarded by that snapshot’s revision
and deletion marker, so hook normalization cannot race a second read. The
caller must first run the registry normalizer/validator against this snapshot.
This shared canonical/atomic seam prepares all patch fields with the owning
kind’s property policy (the value
VerbRegistry::prepare_note_update_policyreturned for this snapshot), then derives and attaches the owner’s typed graph effects. It returns the projected note and one atomic plan, preserving the caller’s operation index. - validate_
note_ update_ expected_ kind - Enforce a caller’s explicit update-kind discriminator against a resolved note before any pack hook can inspect or normalize the request. Canonical KG dispatch performs this mismatch check before its hook; the atomic adapter calls this same helper to preserve that error ordering.