diff --git a/CHANGELOG.md b/CHANGELOG.md index bfaf316b..1f210410 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to the Toolpath workspace are documented here. +## toolpath 0.7.2 — 2026-08-21 + +Adds an optional `title` field to `StepMeta`, completing the set: +`GraphMeta` and `PathMeta` already had it. A short human-readable title +for the step, first-class in the JSON Schema and typed structs; existing +documents are unaffected. + ## toolpath 0.7.1 — 2026-08-14 Adds an optional `description` field to `StepMeta`, `PathMeta`, and diff --git a/Cargo.lock b/Cargo.lock index 24b36aeb..bc6f1167 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4218,7 +4218,7 @@ checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" [[package]] name = "toolpath" -version = "0.7.1" +version = "0.7.2" dependencies = [ "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index d823e0e2..c244937b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ edition = "2024" license = "Apache-2.0" [workspace.dependencies] -toolpath = { version = "0.7.1", path = "crates/toolpath" } +toolpath = { version = "0.7.2", path = "crates/toolpath" } toolpath-convo = { version = "0.11.1", path = "crates/toolpath-convo" } toolpath-git = { version = "0.6.0", path = "crates/toolpath-git" } toolpath-claude = { version = "0.12.2", path = "crates/toolpath-claude", default-features = false } diff --git a/RFC.md b/RFC.md index 376339b1..b1ce4a91 100644 --- a/RFC.md +++ b/RFC.md @@ -281,6 +281,7 @@ paths. | Field | Description | | ------------- | -------------------------------------------------- | +| `title` | Short human-readable title | | `kind` | Path kind — see [Document Kind](#document-kind) (paths only) | | `intent` | The initial goal of the work | | `description` | Human-readable summary of the object itself | diff --git a/crates/toolpath/Cargo.toml b/crates/toolpath/Cargo.toml index 7d3fe8f3..4f3ed57e 100644 --- a/crates/toolpath/Cargo.toml +++ b/crates/toolpath/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "toolpath" -version = "0.7.1" +version = "0.7.2" edition.workspace = true license.workspace = true repository = "https://github.com/empathic/toolpath" diff --git a/crates/toolpath/schema/toolpath.schema.json b/crates/toolpath/schema/toolpath.schema.json index b4bf57d9..4fabd603 100644 --- a/crates/toolpath/schema/toolpath.schema.json +++ b/crates/toolpath/schema/toolpath.schema.json @@ -205,6 +205,10 @@ "type": "object", "description": "Optional metadata for a step", "properties": { + "title": { + "type": "string", + "description": "Human-readable title" + }, "intent": { "type": "string", "description": "The initial goal of the work" diff --git a/crates/toolpath/src/jsonl.rs b/crates/toolpath/src/jsonl.rs index a3604032..0e1e978a 100644 --- a/crates/toolpath/src/jsonl.rs +++ b/crates/toolpath/src/jsonl.rs @@ -675,7 +675,8 @@ fn write_line(w: &mut W, line: &JsonlLine) -> Result<(), JsonlError> { } fn step_meta_is_empty(m: &StepMeta) -> bool { - m.intent.is_none() + m.title.is_none() + && m.intent.is_none() && m.description.is_none() && m.source.is_none() && m.refs.is_empty() @@ -1212,6 +1213,32 @@ mod tests { assert_eq!(canonical_json(&p), canonical_json(&back)); } + #[test] + fn roundtrip_step_title() { + let mut step = make_step("s1", None); + step.meta = Some(StepMeta { + title: Some("Rename config field".into()), + ..Default::default() + }); + let p = Path { + path: PathIdentity { + id: "p".into(), + base: None, + head: "s1".into(), + graph_ref: None, + }, + steps: vec![step], + meta: None, + }; + let jsonl = p.to_jsonl_string().unwrap(); + let back = Path::from_jsonl_str(&jsonl).unwrap(); + assert_eq!(canonical_json(&p), canonical_json(&back)); + // Typed field, not the extra catch-all. + let meta = back.steps[0].meta.as_ref().unwrap(); + assert_eq!(meta.title.as_deref(), Some("Rename config field")); + assert!(meta.extra.is_empty()); + } + #[test] fn roundtrip_description() { let mut step = make_step("s1", None); diff --git a/crates/toolpath/src/types.rs b/crates/toolpath/src/types.rs index 0c480367..d2a8955b 100644 --- a/crates/toolpath/src/types.rs +++ b/crates/toolpath/src/types.rs @@ -280,6 +280,8 @@ pub struct StructuralChange { /// Step metadata #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct StepMeta { + #[serde(default, skip_serializing_if = "Option::is_none")] + pub title: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub intent: Option, #[serde(default, skip_serializing_if = "Option::is_none")] diff --git a/site/_data/crates.json b/site/_data/crates.json index 898a045c..49c8e5de 100644 --- a/site/_data/crates.json +++ b/site/_data/crates.json @@ -1,7 +1,7 @@ [ { "name": "toolpath", - "version": "0.7.1", + "version": "0.7.2", "description": "Core types, builders, and query API", "docs": "https://docs.rs/toolpath", "crate": "https://crates.io/crates/toolpath",