Skip to main content

Module anchor

Module anchor 

Source
Expand description

Anchors — engine-owned durable provenance records tying an entity to the source artifacts it describes.

An anchor is the projection pipeline’s single new load-bearing primitive: which artifact (in the medium’s own namespace), at which grain, under which provenance class, at which medium-typed version, hashed over the prepared artifact form (never raw bytes) where the class carries hash semantics, and the medium’s declared hash stability — so an unstable-source hash break resolves as AnchorState::Recheck, not AnchorState::Drifted.

§Naming

The Anchor* family is deliberately distinct from the three provenance-adjacent type families already in the tree — it never reuses Provenance / ProvenanceKind (the mutation-log record in crate::provenance), nor ArchiveProvenance / EntityProvenance / History (the authoring-provenance payload in memstead_schema::archive_provenance). Those stay; anchors are a separate concern (source→entity provenance, not mutation history nor authoring lineage).

§Wire vocabulary (fixed contract)

  • provenance classes: anchored / derived / authored / informed-by
  • grains: span / file / tree / url / entity
  • hash stability: stable / unstable
  • resolution states: resolves / drifted / recheck / orphaned

The Rust identifiers around this vocabulary are the implementer’s choice; the wire strings are the contract and are locked by the *_wire_strings_are_stable tests below.

§Storage

Anchors persist in an engine-owned sidecar on the mem branch under ANCHOR_SIDECAR_PATH (.memstead/anchors.json) — see AnchorSidecar. The sidecar is written only through engine commits (the crate::backend::MemBackend sidecar seam); every external reader already filters the .memstead/ namespace, so an anchor-only commit yields no entity deltas and does not participate in _hash.

§Scope of this module

Pure value types, wire (de)serialisation, validation (typed INVALID_ANCHOR refusals with recovery detail), and the resolution model. No storage or IO lives here — the backend seam and the mutation/CLI wiring consume these types.

Structs§

Anchor
One durable anchor record: an entity’s provenance tie to a single source artifact.
AnchorInput
A permissive wire-shaped anchor element as it arrives on a mutation’s anchors[] parameter. All fields are optional / string-typed so an unknown class or grain surfaces as a typed AnchorValidationError with recovery detail rather than an opaque serde failure. Call Self::validate to obtain a strict Anchor.
AnchorSidecar
The engine-owned anchors sidecar document persisted at ANCHOR_SIDECAR_PATH on the mem branch: entity id → its anchors.
AnchorUnset
A validated explicit-removal selector: which of an entity’s anchors an update’s anchors_unset[] entry removes. Selection is by artifact, optionally narrowed by grain and/or class; a selector matching nothing is a no-op (removal is idempotent — its job in recovery flows is “make sure this is gone”).
AnchorUnsetInput
A permissive wire-shaped anchors_unset[] element — an explicit removal selector on the update surface. Each entry names an artifact and may narrow by grain and/or class; a bare artifact selects every anchor on it. String-typed like AnchorInput so an unknown grain or class refuses typed (INVALID_ANCHOR) rather than silently selecting nothing forever. Call Self::validate to obtain a strict AnchorUnset.
EntityAnchorComposition
Per-entity provenance-class + grain composition, computed from an entity’s anchor list. Tree-grain fan-out is surfaced distinctly so a single entity anchored to a large tree is never laundered into full per-file credit — the count of tree anchors is visible on its own axis, and downstream (E3b) reads the fan-out counts from resolution.
ObservedArtifactHash
One verify-observed prepared-content hash, addressed to the anchor(s) it backfills: the (entity, artifact) pair a hash-less hash-bearing anchor is keyed by in the sidecar, plus the hash the observation computed. The verify pass collects these; the engine’s sidecar writer records them.

Enums§

AnchorGrain
The granularity of the artifact reference an anchor carries.
AnchorHashStability
The medium’s declared hash stability — whether a change in the prepared-content hash is a reliable drift signal.
AnchorProvenanceClass
The epistemic standing of an anchor — how the entity relates to the artifact it references.
AnchorState
The resolved state of one anchor against the current medium.
AnchorValidationError
A typed INVALID_ANCHOR refusal. The whole mutation refuses and the entity is not written; Self::detail carries the recovery payload (offending value + allowed set) the agent fixes from.
AnchorVersion
A medium-typed pinned version the anchor was recorded against.
ArtifactObservation
What the engine observed about an anchor’s artifact when resolving.

Constants§

ANCHOR_SIDECAR_PATH
Mem-relative path of the engine-owned anchors sidecar on the mem branch. Lives under the .memstead/ umbrella every external reader already treats as non-entity, so an anchor-only commit produces zero entity deltas.
ANCHOR_SIDECAR_VERSION
Current sidecar document schema version.
INVALID_ANCHOR_CODE
Stable typed error code returned when an anchors[] element is malformed. Mirrors the engine’s other typed-envelope codes; the whole mutation refuses and the entity is not written.

Functions§

compose_entity_anchors
Compose an entity’s anchors into class/grain counts, derived inputs, and the tree-grain fan-out axis.
prepared_content_hash
Compute the prepared-content hash of a path-grain artifact’s bytes — the value Anchor::hash records and hash-drift adjudication compares.
resolve_anchor
Resolve one anchor against a current observation, honouring the class’s hash semantics and the medium’s declared stability.