pub enum ProjectionCommand {
Brief(BriefArgs),
Init(InitArgs),
Migrate(MigrateArgs),
Enable(EnableArgs),
Edit(EditArgs),
Advance(AdvanceArgs),
Exclude(ExcludeArgs),
Verify(VerifyArgs),
CheckPath(CheckPathArgs),
}Variants§
Brief(BriefArgs)
Render a binding’s run-brief — the Markdown prompt an agent consumes —
on stdout. Takes the canonical binding id <mem>/<stem> (D3), e.g.
engine/graph. Omit the id (or pass --all) to select the next due
(binding, operation) pair by round-robin + backoff and render that
operation’s brief; --operation picks which operations rotate (default
build — the classic build-only rotation; any rotates every
loop-declared build / sync / verify pair). An operation participates
only where its binding block declares trigger: loop. Reads the v2
binding store and the destination mem’s schema / writing guidance; the
assembly lives in the engine, so every consuming surface renders
byte-identical briefs by construction.
--verify renders the verify brief (group C) for the named binding:
measurement + capped-adjudication instructions only, with no
destination-mutation instruction. --sync renders the sync brief —
the sole maintenance-writer prompt, carrying both the cursor slice and the
open verify findings in one brief with the absorbed reconcile
conservatism. Both are read-only on the mem; the sync brief’s repairs
reach the mem only when an agent acts on it through the MCP mutation
surface.
Init(InitArgs)
Scaffold a fresh v2 binding non-interactively: ONE record with one
inline source, at .memstead/projections/<mem>/<stem>.json.
All inputs are flags — no prompts ever (parity across callers). The
default binding declares build+sync+verify where the medium permits:
a web source scaffolds build-only, with the deferral named in
warnings[]. A prune block is scaffolded wherever sync survived,
with the strongest guarantee the medium supports (never-clobber for a
git-backed source). Refuses PROJECTION_EXISTS (without touching disk)
when a binding of the same id already exists — never overwrites.
Migrate(MigrateArgs)
Migrate every prior on-disk generation into v2 single-record
bindings, in place. Gen-1 — the root-folder
scopes|projections|ingests/ JSON layout — is first materialized
into the four-primitive store, then folded. Gen-2 — the
four-primitive store (per-mem Projection + flat Ingest) — merges
each ingest into its projection and folds the referenced facets +
mediums inline. v1 — the three-file store — folds each binding’s
facet references inline the same way, source names preserved
byte-verbatim (they key sync watermarks). The emptied mediums/ and
facets/ trees are removed; orphan records refuse rather than drop.
refinement mode and dangling refs refuse with a typed error.
Idempotent on a migrated store. Use --dry-run to preview without
writing.
Enable(EnableArgs)
Enable a build / sync / verify operation on an existing binding by
adding its block (with sensible defaults) if absent. This is the remedy
a refused mutating operation cites (D6): projection enable sync <binding>. Before writing, the operation is checked against the
medium-capability matrix (D6) — enabling sync/verify over a medium
that cannot support it (e.g. a web source) refuses with the capability
gap and writes nothing. Enabling an already-present operation refuses
PROJECTION_OP_ALREADY_ENABLED; a missing binding refuses
PROJECTION_NOT_FOUND.
Edit(EditArgs)
Patch an existing binding’s author-editable fields in place — the
general edit surface over the shared pipeline_edit layer that
init/enable already use. The patch is a JSON object with patch
semantics: an absent field is preserved, an explicit null clears
intent/rules/prune, and a present sources, operations,
reference_mems or deny_paths value replaces that whole block
(version stays engine-managed and is ignored if supplied). Every
edit is validated before anything lands: a patch that would
introduce a refusal the stored record does not already carry (a
duplicate source name, sync over a medium with no change signal)
refuses with the capability gap and writes nothing — pre-existing
refusals never block an unrelated edit. Refuses
PROJECTION_NOT_FOUND for a missing binding; adding a source to a
binding is edit <binding> --patch '{"sources":[...]}' with the
FULL source list, existing entries included, since the block
replaces.
Advance(AdvanceArgs)
Advance a binding’s sync baseline by recording per-artifact
dispositions (D7). The engine freezes the presented changed slice,
subtracts already-disposed artifacts on re-presentation, appends
new-HEAD deltas when the source moves mid-pass, and — when the
remainder empties — advances the destination mem’s #synced token via
the sync-state writer (provenance piggybacks that commit). Dispositions
are durable (.memstead/state/advance/), so a partial pass resumes
across process restarts. The gate accepts only artifact ids the
engine presented — an unknown id refuses the whole call atomically
(PROJECTION_ADVANCE_UNKNOWN_ARTIFACT). In this cycle the agent supplies
a disposition for every artifact explicitly (auto-derivation lands
later).
Exclude(ExcludeArgs)
Declare authored exclusions for in-scope source artifacts. Unlike
advance (whose gate accepts only artifacts in the changed slice), this
gates on enumerable S(D) membership, so a stable, unchanged artifact can
be recorded as deliberately not-modeled with a rationale. Each accepted
(artifact, rationale) lands in the durable exclusion ledger the fidelity
report consults, so the artifact stops re-surfacing as uncovered under
exhaustive coverage and keeps its reasoning. An id may be written in
either form, the workspace-relative one the report uses or the
source-relative one (relative to the source’s pointer): it is resolved
through the binding’s source join at exclude time, the ledger holds the
canonical workspace-relative id, and the response lists what was
recorded. An id that resolves to no artifact of S(D) refuses the
whole call atomically (PROJECTION_EXCLUDE_NOT_SOURCE_MEMBER, naming
the nearest known ids); re-declaring merges into the ledger. On a
binding with several primary sources, a source-relative id that
resolves under MORE THAN ONE of them is likewise refused whole
(PROJECTION_EXCLUDE_AMBIGUOUS_ARTIFACT), naming every canonical id
it could denote in the message and under details.ambiguous: the
engine never picks a source the caller did not name, and either
canonical id is the unambiguous recovery. The write
path for the option-(a)
process-mem judgment migration, and the general “this in-scope artifact is
mined and warrants no destination entity, because …” capability.
Verify(VerifyArgs)
Measure a binding’s fidelity and record durable findings (E3b, group A).
Read-only on the destination mem’s ENTITIES: verify adjudicates its anchors
against the live source and samples in-scope artifacts, writing findings
keyed by the binding’s hash(D) alone into the engine-owned findings store
(.memstead/state/findings/); the source_head a finding was observed
at is carried as metadata, so findings survive source-head movement and
stay presented until a later verify supersedes them. A
binding-declaration edit changes hash(D) and segregates prior
findings as superseded, never presented as current. Verify mutates no entity — any
repair routes through the (later) sync brief — but it is not a pure read:
a completed run records the findings store and backfills observed content
hashes onto hash-less anchors (measurement machinery, without which an anchor
never leaves recheck). The #verified freshness baseline moves only under
--advance, so a gate that verifies in order to read leaves the mem’s config
byte-identical. It then renders the
deterministic, token-budgeted tier-1 fidelity report (group B) over
the findings just recorded: grain-classed coverage (an artifact ruled out
by projection exclude is dropped from coverage.uncovered and counted
beside it as coverage.excluded, so the uncovered figure is the number
still owed) with tree-anchor
fan-out on its own axis, anchor-resolution %, freshness vs. both
sync_state tokens (signal: none → freshness unknowable), the
capability-matrix block, and the tier-3 backlog depth — aggregates always
ship; heavy per-artifact lists greedy-fill under --budget and drop to
hints (forced back in with --include).
The anchor figures answer for THIS BINDING’S population only: anchors another binding wrote, and anchors pointing outside this binding’s declared scope, are excluded from every figure and named in the report rather than dropped. They are never deleted or rewritten: exclusion is a reporting decision. The report states what its denominator counted (anchor rows, with the distinct-artifact count beside them, since one artifact legitimately carries several rows), and says so when anchors recording no producing binding are included by the pre-provenance fallback.
A destination mem that is QUARANTINED (its schema pin unresolved, its
mount unbacked) refuses the run outright with MEM_QUARANTINED and its
boot reason, on both verify and brief --verify: a mem serving no
entities would read as every artifact uncovered and every anchor
absent, which is a measurement neither can honestly make. The refusal
is placed above every store the run would otherwise write, so the
findings store, the #verified token and the authored exclusions in
the advance file all come through byte-identical.
A sidecar row whose ENTITY the mem no longer holds is reported as dangling and named, in no figure and never as resolving: it is a sidecar integrity condition, not an anchor state, and nothing repairs it, because the row is the trace of a writer that went around the engine. Where the entity end could not be reconciled at all (an unloaded, quarantined or partly unparsed mem), the report says so rather than reporting a clean anchor axis.
CheckPath(CheckPathArgs)
Answer deny verdicts: is a path (or Glob/Grep pattern) hidden by a
binding’s deny_paths? Evaluates each candidate against the named
binding — or, with --binding omitted, the ACTIVE binding (the one
whose brief was last consumed) — using the engine’s own deny dialect:
the facet-scope glob grammar, resolved against the workspace root (an ingest deny spans every source, so it has no pointer to be relative to), plus
the literal-base directory-prefix rule (dev/** also blocks a read of
dev itself). Single-path form takes the candidate as an argument;
--batch reads {"cwd": "<dir>", "paths": ["...", ...]} from stdin
and answers every candidate in one process — the form a per-tool-call
consumer (the plugin’s PreToolUse deny hook) amortizes subprocess cost
with. Engine-free and read-only: verdicts come from the binding record
and the path alone, no workspace boot. Output names the matched deny
entry on a block; the exit code stays 0 for an answered check — a
non-zero exit means the check itself could not run (unknown or
quarantined binding, no active binding, malformed batch).
Trait Implementations§
Source§impl Debug for ProjectionCommand
impl Debug for ProjectionCommand
Source§impl FromArgMatches for ProjectionCommand
impl FromArgMatches for ProjectionCommand
Source§fn from_arg_matches(__clap_arg_matches: &ArgMatches) -> Result<Self, Error>
fn from_arg_matches(__clap_arg_matches: &ArgMatches) -> Result<Self, Error>
Source§fn from_arg_matches_mut(
__clap_arg_matches: &mut ArgMatches,
) -> Result<Self, Error>
fn from_arg_matches_mut( __clap_arg_matches: &mut ArgMatches, ) -> Result<Self, Error>
Source§fn update_from_arg_matches(
&mut self,
__clap_arg_matches: &ArgMatches,
) -> Result<(), Error>
fn update_from_arg_matches( &mut self, __clap_arg_matches: &ArgMatches, ) -> Result<(), Error>
ArgMatches to self.Source§fn update_from_arg_matches_mut<'b>(
&mut self,
__clap_arg_matches: &mut ArgMatches,
) -> Result<(), Error>
fn update_from_arg_matches_mut<'b>( &mut self, __clap_arg_matches: &mut ArgMatches, ) -> Result<(), Error>
ArgMatches to self.Source§impl Subcommand for ProjectionCommand
impl Subcommand for ProjectionCommand
Source§fn augment_subcommands<'b>(__clap_app: Command) -> Command
fn augment_subcommands<'b>(__clap_app: Command) -> Command
Source§fn augment_subcommands_for_update<'b>(__clap_app: Command) -> Command
fn augment_subcommands_for_update<'b>(__clap_app: Command) -> Command
Command so it can instantiate self via
FromArgMatches::update_from_arg_matches_mut Read moreSource§fn has_subcommand(__clap_name: &str) -> bool
fn has_subcommand(__clap_name: &str) -> bool
Self can parse a specific subcommandAuto Trait Implementations§
impl Freeze for ProjectionCommand
impl RefUnwindSafe for ProjectionCommand
impl Send for ProjectionCommand
impl Sync for ProjectionCommand
impl Unpin for ProjectionCommand
impl UnsafeUnpin for ProjectionCommand
impl UnwindSafe for ProjectionCommand
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> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<T> Fruit for T
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