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:
- Pick the right sub-struct under
CorePolicy/AtomisationPolicy/ etc. - Add the field (with
#[serde(default, skip_serializing_if = "Option::is_none")]). - Add the field to the sub-struct’s
Defaultimpl.
No literal-site cascade. The ..Default::default() pattern used
at every construction site picks up the new field automatically.
Fields§
§core: CorePolicyAccess-control + inheritance + reflection-depth — the
load-bearing K9/K10 governance knobs. See CorePolicy.
atomisation: AtomisationPolicyWT-1-D + Form 2 atomisation knobs. See AtomisationPolicy.
synthesis: SynthesisPolicyForm 1 synthesis curator knobs + legacy per-pair opt-in. See
SynthesisPolicy.
multistep: MultistepPolicyForm 3 multistep-ingest prompt sizing knobs. See
MultistepPolicy.
kind_class: KindClassificationPolicyForm 6 memory-kind auto-classifier knobs. See
KindClassificationPolicy.
persona: PersonaPolicyQW-2 persona auto-regeneration cadence + file-backed export
knobs. See PersonaPolicy.
export: ExportPolicyQW-1 reflection-export knob. See ExportPolicy.
Implementations§
Source§impl GovernancePolicy
impl GovernancePolicy
Sourcepub fn from_metadata(metadata: &Value) -> Option<Result<Self, Error>>
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.
Sourcepub fn default_for_managed_namespace() -> Self
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.
Sourcepub fn effective_max_reflection_depth(&self) -> u32
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.
Sourcepub fn effective_auto_export_reflections_to_filesystem(&self) -> bool
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.
Sourcepub fn effective_auto_atomise(&self) -> bool
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.
Sourcepub fn effective_auto_atomise_threshold_cl100k(&self) -> u32
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).
Sourcepub fn effective_auto_atomise_max_atom_tokens(&self) -> u32
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.
Sourcepub fn effective_auto_atomise_max_retries(&self) -> Option<u32>
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.
Sourcepub fn effective_auto_persona_trigger_every_n_memories(&self) -> Option<u32>
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.
Sourcepub fn effective_auto_export_personas_to_filesystem(&self) -> bool
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.
Sourcepub fn effective_auto_atomise_mode(&self) -> AutoAtomiseMode
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):
auto_atomise_mode = Some(mode)wins — operator explicit.- Otherwise
auto_atomise = Some(true)→AutoAtomiseMode::Deferred(preserves pre-Form-2 deployments verbatim). - Otherwise
AutoAtomiseMode::Off.
Both Off returns and an Off explicit override short-circuit
the pre_store hook chain entirely.
Sourcepub fn effective_legacy_per_pair_classifier(&self) -> bool
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.
Sourcepub fn effective_synthesis_failure_mode(&self) -> SynthesisFailureMode
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.
Sourcepub fn effective_synthesis_max_deletes_per_call(&self) -> u32
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.
Sourcepub fn effective_synthesis_max_candidate_chars(&self) -> usize
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.
Sourcepub fn effective_multistep_max_content_chars(&self) -> usize
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.
Sourcepub fn effective_auto_classify_kind(&self) -> MemoryKindAutoClassify
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
impl Clone for GovernancePolicy
Source§fn clone(&self) -> GovernancePolicy
fn clone(&self) -> GovernancePolicy
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for GovernancePolicy
impl Debug for GovernancePolicy
Source§impl Default for GovernancePolicy
impl Default for GovernancePolicy
Source§fn default() -> GovernancePolicy
fn default() -> GovernancePolicy
Source§impl<'de> Deserialize<'de> for GovernancePolicy
impl<'de> Deserialize<'de> for GovernancePolicy
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for GovernancePolicy
Source§impl PartialEq for GovernancePolicy
impl PartialEq for GovernancePolicy
Source§fn eq(&self, other: &GovernancePolicy) -> bool
fn eq(&self, other: &GovernancePolicy) -> bool
self and other values to be equal, and is used by ==.Source§impl Serialize for GovernancePolicy
impl Serialize for GovernancePolicy
impl StructuralPartialEq for GovernancePolicy
Auto Trait Implementations§
impl Freeze for GovernancePolicy
impl RefUnwindSafe for GovernancePolicy
impl Send for GovernancePolicy
impl Sync for GovernancePolicy
impl Unpin for GovernancePolicy
impl UnsafeUnpin for GovernancePolicy
impl UnwindSafe for GovernancePolicy
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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