Skip to main content

GovernancePolicy

Struct GovernancePolicy 

Source
pub struct GovernancePolicy {
    pub core: CorePolicy,
    pub atomisation: AtomisationPolicy,
    pub synthesis: SynthesisPolicy,
    pub multistep: MultistepPolicy,
    pub kind_class: KindClassificationPolicy,
    pub persona: PersonaPolicy,
    pub export: ExportPolicy,
}
Expand description

Governance policy attached to a namespace’s standard memory (stored in metadata.governance).

Default policy when a standard has no metadata.governance: { write: Any, promote: Any, delete: Owner, approver: Human, inherit: true }.

v0.6.2 (S34 defensive): promote, delete, and approver carry #[serde(default)] so partial-policy payloads (a common shape for operator CLIs / test harnesses that only care about write) round-trip instead of 400-ing out on missing fields. write remains required — it’s the core knob a policy is attempting to set.

v0.6.3.1 (P4, audit G1): inherit controls whether parent-namespace policies bubble up. Default true matches the architecture page T2 promise of “Hierarchical policy inheritance (default at org/, overridable at org/team/)”. Setting inherit: false on a child stops the leaf-first walk in resolve_governance_policy, providing an explicit opt-out path for scoped overrides (e.g. an audit sandbox under a fully-governed parent).

§#880 / #793 PR-3 — decomposition (2026-05-18)

Pre-#880 the struct carried 20 flat fields. Adding any new field forced a 50-site struct-literal cascade across src/ + tests/ (the surface this issue closes). Post-#880 the same 20 fields are grouped into 7 per-concern sub-structs and re-attached to the parent via #[serde(flatten)]. The composite still carries every field, so the wire-format / TOML / metadata.governance JSON shape is unchanged (pinned by tests/governance_policy_wire_compat.rs). Each existing field is still reachable via the new policy.core.write, policy.atomisation.auto_atomise, etc. paths, and every effective_* accessor on the parent struct delegates to the matching sub-struct so the rest of the codebase that calls policy.effective_max_reflection_depth() is unchanged.

Adding a new policy knob now means:

  1. Pick the right sub-struct under CorePolicy / AtomisationPolicy / etc.
  2. Add the field (with #[serde(default, skip_serializing_if = "Option::is_none")]).
  3. Add the field to the sub-struct’s Default impl.

No literal-site cascade. The ..Default::default() pattern used at every construction site picks up the new field automatically.

Fields§

§core: CorePolicy

Access-control + inheritance + reflection-depth — the load-bearing K9/K10 governance knobs. See CorePolicy.

§atomisation: AtomisationPolicy

WT-1-D + Form 2 atomisation knobs. See AtomisationPolicy.

§synthesis: SynthesisPolicy

Form 1 synthesis curator knobs + legacy per-pair opt-in. See SynthesisPolicy.

§multistep: MultistepPolicy

Form 3 multistep-ingest prompt sizing knobs. See MultistepPolicy.

§kind_class: KindClassificationPolicy

Form 6 memory-kind auto-classifier knobs. See KindClassificationPolicy.

§persona: PersonaPolicy

QW-2 persona auto-regeneration cadence + file-backed export knobs. See PersonaPolicy.

§export: ExportPolicy

QW-1 reflection-export knob. See ExportPolicy.

Implementations§

Source§

impl GovernancePolicy

Source

pub fn from_metadata(metadata: &Value) -> Option<Result<Self, Error>>

Parse a policy out of a metadata.governance JSON value. Returns None when the field is missing/null. Parse errors propagate so callers can surface them to the user instead of silently defaulting.

Source

pub fn default_for_managed_namespace() -> Self

NHI-P4-T19 (v0.7.0 NHI testing): default policy for namespaces that have a standard set but no explicit metadata.governance. Differs from Default::default (write=Any) by tightening write to Owner — calling memory_namespace_set_standard implies the operator wants enforcement, not advisory-only. Operators who want write=Any must set it explicitly in the standard memory’s metadata. Tested in db::tests::namespace_set_standard_default_write_is_owner.

Source

pub fn effective_max_reflection_depth(&self) -> u32

v0.7.0 recursive-learning Task 2/8 (issue #655): resolve the per-namespace reflection-depth cap. Returns the operator’s override when present, otherwise the compiled-in default of 3.

Why 3? Bounds recursion (reflection-on-reflection-on-…) without strangling the legitimate “reflection-on-reflection” chains the v0.8.0 Pillar 2.5 curator mode will lean on. Operators who want a different global default should change the constant in this accessor; per-namespace overrides should stay in the JSON metadata blob.

Some(0) disables reflection entirely. Task 5/8 enforces the rule proposed_reflection_depth >= cap → refuse, so a cap of 0 refuses every reflection (no depth >= 0 passes the comparison). This is the documented kill-switch for a namespace that should never accept reflection writes.

Ancestor inheritance is not walked here — that’s the job of db::resolve_governance_policy (and the equivalent store trait method), which returns the most-specific policy via the leaf-first namespace chain walk. Callers at the memory_reflect MCP write path resolve the policy first, then call this accessor on the result.

Source

pub fn effective_auto_export_reflections_to_filesystem(&self) -> bool

v0.7.0 QW-1 — resolve the file-backed-export policy. Returns false (substrate stays SQL-canonical) when the namespace has no explicit override. Some(true) opts the namespace into the deferred filesystem write in the substrate post_reflect hook.

Inheritance is not walked here — the caller resolves the most-specific policy via resolve_governance_policy and then queries this accessor on the result, mirroring how effective_max_reflection_depth is consumed.

Source

pub fn effective_auto_atomise(&self) -> bool

v0.7.0 WT-1-D — resolve the auto-atomisation enable flag. Returns false (substrate stays quiet) when the namespace has no explicit override. Some(true) opts the namespace into the pre_store substrate hook’s deferred curator-pass enqueue.

Inheritance is not walked here — the caller resolves the most-specific policy via resolve_governance_policy and then queries this accessor on the result, mirroring how effective_max_reflection_depth is consumed.

Source

pub fn effective_auto_atomise_threshold_cl100k(&self) -> u32

v0.7.0 WT-1-D — resolve the cl100k token threshold above which the auto-atomisation hook fires. Compiled default is 500; matches the WT-1-D brief (memories ≤ 500 tokens are short enough to live as a single observation).

Source

pub fn effective_auto_atomise_max_atom_tokens(&self) -> u32

v0.7.0 WT-1-D — resolve the per-atom token budget for the auto-atomisation curator pass. Compiled default is 200; matches AtomiserConfig::default_max_atom_tokens so the hook-driven path produces atoms indistinguishable from CLI/MCP-driven atomisation.

Source

pub fn effective_auto_atomise_max_retries(&self) -> Option<u32>

v0.7.0 Cluster-F PERF-5 — resolve the Synchronous-mode curator retry budget. Returns None when the namespace has no explicit override; the caller threads this through Atomiser::atomise_sync_with_retries and falls back to AtomiserConfig::sync_curator_max_retries (compiled default 1) when None. Documented in docs/atomisation.md alongside the Synchronous-mode latency envelope.

Source

pub fn effective_auto_persona_trigger_every_n_memories(&self) -> Option<u32>

v0.7.0 QW-2 — resolve the auto-persona regeneration cadence. Returns None (cadence disabled) when the namespace has no explicit override; Some(N) opts the namespace into deferred persona regeneration every N writes against an entity. The post_store hook reads this accessor on the resolved policy after walking the leaf-first ancestor chain.

Source

pub fn effective_auto_export_personas_to_filesystem(&self) -> bool

v0.7.0 QW-2 — resolve the file-backed-export policy for Persona-kind memories. Returns false (substrate stays SQL-canonical) when the namespace has no explicit override. Symmetric with Self::effective_auto_export_reflections_to_filesystem.

Source

pub fn effective_auto_atomise_mode(&self) -> AutoAtomiseMode

v0.7.x Form 2 — resolve the atomisation execution mode.

Resolution rules (matches the table on AutoAtomiseMode):

  1. auto_atomise_mode = Some(mode) wins — operator explicit.
  2. Otherwise auto_atomise = Some(true)AutoAtomiseMode::Deferred (preserves pre-Form-2 deployments verbatim).
  3. Otherwise AutoAtomiseMode::Off.

Both Off returns and an Off explicit override short-circuit the pre_store hook chain entirely.

Source

pub fn effective_legacy_per_pair_classifier(&self) -> bool

v0.7.x Form 1 — resolve the legacy per-pair classifier opt-in. Returns false (default) when absent or Some(false), routing the substrate through the new single-batch action-emitting synthesiser. Some(true) keeps the legacy per-pair binary contradiction call (metadata-only outcome) for operators who depend on the v0.6.x behaviour.

Source

pub fn effective_synthesis_failure_mode(&self) -> SynthesisFailureMode

v0.7.0 Cluster-B (issue #767) — resolve the synthesis-failure policy. Default is SynthesisFailureMode::FallThrough to preserve backward compatibility with the v0.7.0 ship behaviour; operators opt in to SynthesisFailureMode::BlockWrite per namespace when a curator outage must be surfaced loudly.

Source

pub fn effective_synthesis_max_deletes_per_call(&self) -> u32

v0.7.0 Cluster-B (issue #767, SEC-1) — resolve the per-call delete-cap. Compiled default is 1: a single LLM round-trip must not mass-delete a namespace without an explicit K10 approval flow.

Source

pub fn effective_synthesis_max_candidate_chars(&self) -> usize

v0.7.0 Cluster-B (issue #767, PERF-7) — resolve the per-candidate character cap inlined into the synthesis prompt. Compiled default is 1500 characters (~400 cl100k tokens). Truncation only affects the LLM prompt, not the stored row.

Source

pub fn effective_multistep_max_content_chars(&self) -> usize

v0.7.0 polish (issue #782, PERF-11) — resolve the per-stage character cap inlined into a Form 3 multistep-ingest LLM-stage prompt. Compiled default is 1500 characters (~400 cl100k tokens), matching the synthesis cap (PERF-7) so operators have a single reasonable prompt-budget shape to reason about. Truncation only affects the LLM prompt content slot; the helper payloads (which carry their own preview truncation inside the helper) and the caller-visible final output are untouched.

Source

pub fn effective_auto_classify_kind(&self) -> MemoryKindAutoClassify

#880 — auto-classify-kind accessor, missing in the pre-#880 hand-written impl (callers were reading policy.kind_class.auto_classify_kind directly). Now exposed via a typed accessor so the call sites can migrate to the sub-struct path without referencing every field directly.

Trait Implementations§

Source§

impl Clone for GovernancePolicy

Source§

fn clone(&self) -> GovernancePolicy

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for GovernancePolicy

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for GovernancePolicy

Source§

fn default() -> GovernancePolicy

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for GovernancePolicy

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for GovernancePolicy

Source§

impl PartialEq for GovernancePolicy

Source§

fn eq(&self, other: &GovernancePolicy) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for GovernancePolicy

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for GovernancePolicy

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more