Memory policy contract (v1 candidate)¶
MemoryPolicy is the small, explicit contract that binds two different
durable-memory decisions:
MemoryAdmissionPolicydecides whether one concrete, host-owned ingress candidate may be confirmed.LedgerRecallPolicydecides how already active records may be selected for one bounded recall lane.
Those phases are intentionally not aliases. Admission never performs recall;
recall never confirms a candidate. MemoryPolicy gives a host one versioned,
content-free object to review and pass to both explicit boundaries.
It is an additive v1 API-freeze candidate, not a workflow engine, model policy, automatic ingestion feature, or a claim that every existing Ledger adapter is already stable.
Safe default¶
from protoprompt.ledger import MemoryPolicy
policy = MemoryPolicy.safe_default()
assert policy.admission.allowed_origins == ("host_assertion",)
assert policy.recall.require_admission_audit is True
print(policy.explain()) # content-free policy receipt plus fingerprint
The default permits only reviewed host_assertion facts, decisions, and
preferences at confidence 0.75 or above. It does not create a record or
admit user, document, tool, or model text by itself.
Explicit host integration¶
The host still owns the scope, ingress, review, and request boundary. Pass the matching components explicitly rather than exposing the wrapper to a model or browser client:
from protoprompt import MemoryScope
from protoprompt.ledger import (
MemoryPolicy,
MemoryReviewGate,
MemoryWriter,
SqliteMemoryLedger,
)
from protoprompt.ledger.recall import LedgerRecallPlanner
ledger = SqliteMemoryLedger("ledger.db")
ledger.setup()
writer = MemoryWriter(
ledger,
scope=MemoryScope(tenant="local", user="alice", thread="chat-42"),
)
policy = MemoryPolicy.safe_default()
gate = MemoryReviewGate(
writer,
origin="host_assertion",
policy=policy.admission,
)
planner = LedgerRecallPlanner(writer, policy=policy.recall)
For a custom policy, construct both components deliberately. The recall
component must be at least as restrictive as admission; otherwise
MemoryPolicy(...) fails during construction.
Enforced relationship¶
MemoryPolicy rejects a pair unless all of these are true:
- recall requires immutable admission-audit evidence;
- recall declares concrete origins instead of the legacy unrestricted-origin
compatibility lane, excluding
unknownandlegacy_unknown; - recall origins and kinds are subsets of the admission origins and kinds;
- recall's minimum confidence is no lower than admission's minimum confidence.
This means a record selected through the combined contract could have passed its paired admission rule. It is an API-shaping safety invariant, not a Python sandbox or authorization system.
Receipt and versioning¶
policy.explain() returns fresh JSON-safe metadata: the wrapper schema,
policy identity/version, both nested component receipts, and a deterministic
content-free fingerprint. It never contains memory text, scopes, record IDs,
task text, secrets, or provider messages.
schema_version, policy_id, and policy_version belong to the wrapper.
The nested admission and recall policies retain their own compatibility
versions. Persist an application's exact reviewed policy receipt next to its
deployment configuration; do not assume that matching human-readable names
mean matching semantics.
Boundaries¶
- Existing standalone
MemoryAdmissionPolicyandLedgerRecallPolicyuses remain supported as experimental compatibility APIs. They are not silently converted intoMemoryPolicy. MemoryPolicydoes not changeMemoryWriter, auto-wire legacy vector or transcript storage, solve prompt injection, arbitrate conflicts, or send a provider request.- The host must still protect its Ledger/database, scope assignment, review authority, and any checkpoint secrets. See the Memory Ledger and bounded Ledger recall guides for their separate lifecycle and request-boundary constraints.