Skip to main content

Module model

Module model 

Source
Expand description

The descriptor: everything a projection may say about a capability, and nothing else.

§What this module owns

Capability is the value the whole executable is a projection of. It carries identity (CapabilityId, ModuleId), what the thing is (CapabilityKind), the canonical schemas of its input and output, where it came from (Provenance), where it is projected (Exposure), where it means anything (Availability), who it is for (Visibility), where it stands (Stability), and the two operational policies a call is subject to (CachePolicy, BenchmarkPolicy).

§What it deliberately does not own

There is no handler here and no transport type. A descriptor is plain data: it serialises, it round-trips, and it can be read by something that cannot execute anything — which is what lets the generated reference, the site dataset and the OpenAPI document be built from the same value the executor dispatches on. Execution lives in super::handler; the collection and its invariants live in super::registry.

§Declared against classified

Two fields are classified rather than declared: Availability::classify and Visibility::classify compute their values from the kind and the exposures the declaration already carries. Asking each declaration to restate them would be the same knowledge written twice, and the second copy is the one that goes wrong. Both matches are exhaustive with no fallback arm on purpose, so a new kind or a new transport is a compile error here rather than a silent default in a page that then links to nothing.

§Invariants

Nothing in this module enforces anything: a descriptor can be built wrong and the registry is what refuses it. What lives here is the vocabulary each check is written against — the grammar of an id, the shape of a route, the states a policy may be in — each with its own validator returning the reason it failed rather than a boolean.

use majordomus_cli::capability::{
    Availability, CapabilityId, CapabilityKind, CliExposure, Exposure, Visibility,
};

let id = CapabilityId::parse("repository.info").unwrap();
assert_eq!(id.namespace(), "repository");

// a capability offered only on the command line is developer-facing, and needs a
// process to answer at all — neither of which its declaration had to say
let exposure = Exposure {
    cli: Some(CliExposure { path: vec!["scope".into()] }),
    ..Default::default()
};
assert_eq!(Visibility::classify(&exposure), Visibility::Developer);
assert_eq!(
    Availability::classify(CapabilityKind::Query, &exposure),
    Availability::Runtime
);

Structs§

Capability
The canonical descriptor. Everything a projection may say about a capability is here.
CapabilityId
A stable, globally meaningful identity: a namespace, a dot, and a local part. repository.info and objects.get for executables; <kind>.<identity> for a declarative object (rule.majordomus.scope-integrity@1, document.docs/CLI.md, policy..ai/repo/policy.yaml).
CliExposure
How a capability appears on the command line: the words after majordomus.
ExecutionPolicy
What running a capability as an execution means: what it changes, whether asking it to stop achieves anything, and whether two of them may overlap.
Exposure
The projections a capability declares. Absence is explicit: None means not exposed there, and nothing infers an exposure a descriptor did not declare.
Hints
What a caller may assume about a call before making it: the four facts MCP names tool annotations, held once on the model so that no projection states its own.
HttpExposure
How a capability appears over HTTP. GET binds every top-level input property as a query parameter; POST binds the input as the JSON request body. Paths are absolute and live under HttpExposure::PREFIX.
McpExposure
How, if at all, a capability appears to an MCP client.
McpResource
An MCP resource: its URI and the short name a client lists.
ModuleId
A module identity: the namespace of every capability the module composes, matching [a-z][a-z0-9_-]*. Builtin modules declare theirs in module!; a declarative object’s module is its kind.
SkillExposure
A capability as a skill a person invokes by a short name from an agent’s prompt: /intent <sentence> in Claude Code. The name and the one input field the typed text fills are declared here, once; the file an agent product reads is generated from them (the editors module) and carries no description of what the capability does beyond the capability’s own.

Enums§

Availability
Where a capability means anything: the environment a caller must be in for it to answer at all.
BenchmarkPolicy
Whether the capability is a benchmark target. Required is the default and the norm: every executable capability is timed directly and through every transport it is exposed on, with the cases its input type provides.
BenchmarkPrecondition
What a repository must hold before a conditional benchmark requirement applies to it. Typed, like a waiver’s reason, so that the condition is a reviewable statement on the descriptor and never a provider quietly returning nothing.
CachePolicy
Whether, and how, the executor keeps results of this capability. Cache lives in the executor and nowhere else, so MCP, HTTP and the command line share one; the key is the canonical id, the normalised input and the registry fingerprint, so a changed repository never answers from an old entry. The two narrower policies add to the key what the registry fingerprint cannot see: the context’s own reading of the repository (CachePolicy::Generation) and the state of the checkout itself (CachePolicy::Checkout).
CapabilityKind
What a capability is. Three kinds exist because three semantics exist: something that is executed and changes nothing, something that is executed and changes this process’s own memory, and something that is read. A command may also write the repository’s own tracked records, which its kind does not say and its execution policy does (ExecutionPolicy::writes_repository).
Concurrency
Whether two executions of one capability may overlap.
Effect
What running a capability changes outside the caller.
HttpMethod
The HTTP methods a capability may be bound to.
Provenance
Where a capability came from. Never an absolute path.
Stability
Where a capability stands, in the repository’s own vocabulary for claims. A capability that is Planned or Unsupported may be listed but is never executable through any projection; the registry refuses to build otherwise.
Visibility
Who a capability is for, and whether anything offers it.
WaiverReason
Why an executable capability is not benchmarked. Typed, so that a waiver is a reviewable statement and never a convenience; not_executable is the registry’s own reason for resources and is never written by hand.

Constants§

CRATE_DIR
Where this crate lives in the repository, so that a builtin descriptor’s Rust module path names a file a reader can open. A fact of the tree’s layout; the site generator refuses a path that does not exist.
RESERVED_SKILL_NAMES
Names a skill may not take: commands and bundled skills of the agent products that read the projection (Claude Code 2.1), and the words the repository’s own workflow skills are most likely to want. A capability that would be one of these is reached by its MCP tool.