7 stable releases
Uses new Rust 2024
| new 2.2.0 | Jan 20, 2026 |
|---|---|
| 2.1.3 | Dec 29, 2025 |
| 2.1.0 | Dec 25, 2025 |
| 2.0.0 | Dec 13, 2025 |
| 1.0.1 | Dec 2, 2025 |
#171 in Template engine
Used in 2 crates
470KB
11K
SLoC
SpecMan Runtime Library
SpecMan is the runtime foundation for authoring and automating software specifications. It powers workspace discovery, dependency mapping, templating, and lifecycle workflows that keep specs consistent and reproducible.
What It Does
- Discovers workspace roots and canonical directories (
WorkspaceLocator,WorkspacePaths) - Builds dependency graphs for specifications/implementations/scratch pads (
DependencyTree) - Resolves templates (embedded defaults + workspace pointer files) via
TemplateCatalog - Renders Markdown templates deterministically (
MarkdownTemplateEngine) - Provides lifecycle orchestration via the high-level
Specmanfaçade (plan/create/delete) - Exposes structured lifecycle failures (
SpecmanError::Lifecycle(LifecycleError)) so callers can branch programmatically
Getting Started
Add the published crate to your Cargo.toml:
specman = "2"
Or with Cargo:
cargo add specman@2
The ergonomic entrypoint is DefaultSpecman, which wires the default filesystem-backed stack:
use specman::DefaultSpecman;
let specman = DefaultSpecman::from_current_dir()?;
# Ok::<(), specman::SpecmanError>(())
For automation, match lifecycle errors directly instead of parsing strings:
use specman::error::LifecycleError;
use specman::SpecmanError;
fn classify(err: SpecmanError) {
match err {
SpecmanError::Lifecycle(LifecycleError::DeletionBlocked { .. }) => {
// downstream dependents exist
}
SpecmanError::Lifecycle(LifecycleError::PlanTargetMismatch { .. }) => {
// a stale plan was supplied for a different artifact
}
_ => {}
}
}
Reference Validation
Use the reference validator when you need to sanity-check Markdown link destinations inside a workspace. Typical flow:
use specman::{
ReferenceValidationStatus, ReferenceValidator, ValidationMode, discover_workspace,
};
let workspace = discover_workspace(".")?; // or WorkspaceDiscovery::initialize(start)
// Default mode: reachability on, fragments on, transitive traversal on (64 doc limit).
let validator = ReferenceValidator::new(&workspace);
let report = validator.validate("spec/my-spec/spec.md")?;
if report.status == ReferenceValidationStatus::Failure {
for issue in &report.issues {
eprintln!("{:?}: {}", issue.kind, issue.message);
}
}
// To tweak behavior (e.g., disable fragment checks or reachability):
let mut mode = ValidationMode::default();
mode.resolve_fragments = false; // skip heading-fragment verification
mode.reachability = specman::ReachabilityPolicy::Disabled; // syntax-only for https://
let report = ReferenceValidator::with_mode(&workspace, mode).validate("impl/foo/impl.md")?;
Intricate details to be aware of:
- Root locators may be workspace paths or SpecMan handles (
spec://{name},impl://{name},scratch://{slug}); handles found inside Markdown links are rejected asDisallowedHandle. - HTTPS reachability is on by default. Redirects count as success; timeouts surface as
Diagnostic, while 4xx responses becomeErrorand fail the run. - Filesystem targets are resolved relative to the source document, canonicalized, and must stay inside the workspace root; missing files still count as
WorkspaceBoundaryorFileMissingerrors even if they never existed. - Fragment validation uses SpecMan’s slug rules (NFKD + lowercase + punctuation filtering + suffix
-1,-2, ...). Cross-document fragments are validated transitively by default up to 64 Markdown documents. - Images are ignored; inline links, reference-style links, and autolinks are validated. Unresolved reference identifiers are reported as errors.
- Results are deterministic: issues are reported in source order and the report carries both
discoveredreferences andissuesfor consumers.
Repository
All source, issue tracking, and release notes live in the main GitHub repository:
https://github.com/justinbrick/specman
Star the repo or follow along for roadmap updates (including relationship graphing and expanded MCP tool coverage).
Dependencies
~14–19MB
~370K SLoC