toolpath 0.1.0

Types, builders, and query operations for Toolpath provenance documents
Documentation
  • Coverage
  • 37.11%
    36 out of 97 items documented7 out of 7 items with examples
  • Size
  • Source code size: 46.82 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 8.81 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 35s Average build duration of successful builds.
  • all releases: 32s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • akesling

toolpath

Core types, builders, and query operations for Toolpath provenance documents.

Overview

This crate provides the type system for Toolpath -- a format for tracking artifact transformation provenance. It contains:

  • Types: Document, Graph, Path, Step, ArtifactChange, and all supporting structures
  • Builders: Convenient constructors and builder methods for constructing documents
  • Serde: Full serialization/deserialization with #[serde(untagged)] document discrimination
  • Query: Graph traversal and filtering operations on step DAGs

This is the gravity well of the workspace. All other crates depend on toolpath; it depends on nothing except serde and serde_json.

Types

Document (enum: Graph | Path | Step)

Graph
  graph: GraphIdentity { id }
  paths: Vec<PathOrRef>         -- inline Path or $ref
  meta?: GraphMeta

Path
  path: PathIdentity { id, base?, head }
  steps: Vec<Step>
  meta?: PathMeta

Step
  step: StepIdentity { id, parents, actor, timestamp }
  change: HashMap<String, ArtifactChange>
  meta?: StepMeta

Building documents

use toolpath::{Step, Path, Base, ArtifactChange};

// Build a step
let step = Step::new("step-001", "human:alex", "2026-01-29T10:00:00Z")
    .with_parent("step-000")
    .with_raw_change("src/main.rs", "@@ -1,1 +1,1 @@\n-hello\n+world")
    .with_intent("Fix greeting")
    .with_vcs_source("git", "abc123def456");

// Build a path
let path = Path::new(
    "path-pr-42",
    Some(Base::vcs("github:org/repo", "abc123")),
    "step-001",
);

// Branch from another path's step
let base = Base::toolpath("path-main", "step-005");

Query operations

The query module provides graph traversal and filtering over step slices:

use toolpath::query;

// Walk the parent chain from head
let ancestors = query::ancestors(&steps, "step-005");

// Find abandoned branches
let dead_ends = query::dead_ends(&steps, "step-005");

// Filter by actor type
let human_steps = query::filter_by_actor(&steps, "human:");
let agent_steps = query::filter_by_actor(&steps, "agent:");

// Filter by artifact
let main_rs = query::filter_by_artifact(&steps, "src/main.rs");

// Time range
let recent = query::filter_by_time_range(&steps, "2026-01-29T00:00:00Z", "2026-01-30T00:00:00Z");

// Summaries
let all_files = query::all_artifacts(&steps);
let all_actors = query::all_actors(&steps);
let index = query::step_index(&steps);  // id -> &Step

Serialization

Documents roundtrip through JSON:

use toolpath::Document;

let doc = Document::from_json(json_str)?;
let json = doc.to_json_pretty()?;

The Document enum uses #[serde(untagged)] and discriminates by structure: it tries Graph (has graph + paths), then Path (has path + steps), then Step (has step + change).