pub trait SubstrateRead {
// Required methods
fn capabilities(&self) -> Capabilities;
fn grains_of_type(
&self,
grain_type: &str,
namespace: Option<&str>,
opts: ReadOpts,
) -> Result<Vec<GrainRecord>>;
fn grain(&self, hash: &str) -> Result<Option<GrainRecord>>;
// Provided methods
fn heads(&self, _namespace: Option<&str>) -> Result<Vec<HeadGroup>> { ... }
fn telemetry(
&self,
_namespace: Option<&str>,
) -> Result<Option<TelemetryView>> { ... }
fn validate_plan(&self, _workflow: &Value) -> Result<()> { ... }
fn tool_evalset(&self, _tool: &str) -> Result<Option<String>> { ... }
fn embed(&self, _text: &str) -> Result<Option<Vec<f32>>> { ... }
fn address_of(&self, _spec: &GrainSpec) -> Result<Option<String>> { ... }
fn plan_replay(
&self,
_incumbent_plan_hash: &str,
_candidate: &Value,
) -> Result<Option<Value>> { ... }
}Expand description
The read-only slice of the substrate. Analyzers receive this (via
AnalyzeCtx) and nothing else — the trust floor’s “analyzers execute
read-only” is enforced by the type system: a &dyn SubstrateRead cannot
reach any mutating method. It is object-safe (no generics) so
builtin_analyzers() can hand out Box<dyn Analyzer>.
Required Methods§
Sourcefn capabilities(&self) -> Capabilities
fn capabilities(&self) -> Capabilities
Declared optional capabilities.
Sourcefn grains_of_type(
&self,
grain_type: &str,
namespace: Option<&str>,
opts: ReadOpts,
) -> Result<Vec<GrainRecord>>
fn grains_of_type( &self, grain_type: &str, namespace: Option<&str>, opts: ReadOpts, ) -> Result<Vec<GrainRecord>>
Curated read: all grains of one OMS type, optionally namespace-scoped and watermark/liveness filtered.
Provided Methods§
Sourcefn heads(&self, _namespace: Option<&str>) -> Result<Vec<HeadGroup>>
fn heads(&self, _namespace: Option<&str>) -> Result<Vec<HeadGroup>>
Entities with more than one live head. Requires the forks capability;
the default impl reports it missing so non-fork substrates degrade
cleanly rather than pretend.
Sourcefn telemetry(&self, _namespace: Option<&str>) -> Result<Option<TelemetryView>>
fn telemetry(&self, _namespace: Option<&str>) -> Result<Option<TelemetryView>>
A snapshot of the recall-telemetry rollups (§8). Requires the
telemetry capability; the default returns None so substrates without
a sidecar degrade cleanly. namespace scopes the snapshot when set.
Sourcefn validate_plan(&self, _workflow: &Value) -> Result<()>
fn validate_plan(&self, _workflow: &Value) -> Result<()>
Structurally validate a candidate Workflow grain body — the same
checks the runtime would run before executing it (unique and reachable
nodes, conditions parse, every cycle bounded). The engine calls this
before it will stamp a plan_revision as executable, so a proposal
that would produce an unrunnable plan never reaches a reviewer as
something they could apply.
This is deliberately the substrate’s job: the engine owns no plan
grammar, exactly as it owns no CAL grammar (see OmsSubstrate::validate_cal).
Requires the plans capability; the default reports it missing so a
substrate that does not model workflows degrades the proposal to
advisory rather than pretending to have checked it.
Sourcefn tool_evalset(&self, _tool: &str) -> Result<Option<String>>
fn tool_evalset(&self, _tool: &str) -> Result<Option<String>>
The evalset a code revision of tool must be gated against (Rule E1’s
pin). Returns Ok(None) when the tool declares none, which makes a
code_revision for it advisory — an unpinnable revision is one no
gating run could ever satisfy.
Resolved from the substrate and never from the model: a proposer that could name its own grader is not gated.
Sourcefn embed(&self, _text: &str) -> Result<Option<Vec<f32>>>
fn embed(&self, _text: &str) -> Result<Option<Vec<f32>>>
Embed one text through the substrate’s installed embedder — the T1
leg of “is this the same instruction in different words”. Ok(None)
when no embedder is installed (the embeddings capability is off),
so the caller falls back to a lexical measure rather than guessing.
The default reports none; substrates opt in.
Sourcefn address_of(&self, _spec: &GrainSpec) -> Result<Option<String>>
fn address_of(&self, _spec: &GrainSpec) -> Result<Option<String>>
The content address put_grain(spec) WOULD assign, computed without
writing — what lets a rehearsal name the exact grain a live pass
would have stored. Ok(None) when the substrate cannot say (the
default); a replay then reports findings by dedup key and summary.
Sourcefn plan_replay(
&self,
_incumbent_plan_hash: &str,
_candidate: &Value,
) -> Result<Option<Value>>
fn plan_replay( &self, _incumbent_plan_hash: &str, _candidate: &Value, ) -> Result<Option<Value>>
Rehearse a candidate Workflow body against the journaled runs of the
live plan at incumbent_plan_hash — re-driven through the runtime’s
pure scheduler with every effect answered from the journal, nothing
dispatched, nothing written (areev run shadow --plan-file). The
report is the runtime’s ShadowPlanReport as JSON; the engine reads
totals.runs, no_worse, out_of_support_fraction and the per-run
rows. Ok(None) when the substrate has no runtime or no journaled
runs of that plan — the proposal is then simply unrehearsed, never
refused for it. The default reports none.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".