Skip to content

Commit 70a7bbf

Browse files
committed
feat(frontmatter): track status transitions and ensure created_at is set
1 parent 0a362fb commit 70a7bbf

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

rust/leanspec-cli/tests/update.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,21 @@ fn test_update_status_transition() {
4444
let content = read_file(&cwd.join("specs").join("001-my-spec").join("README.md"));
4545
let fm = parse_frontmatter(&content);
4646
assert_eq!(fm.get("status").and_then(|v| v.as_str()), Some("complete"));
47+
48+
// Should record transitions for status changes
49+
let transitions = fm.get("transitions");
50+
assert!(transitions.is_some(), "expected transitions in frontmatter");
51+
if let Some(serde_yaml::Value::Sequence(seq)) = transitions {
52+
// planned -> in-progress -> complete
53+
assert!(seq.len() >= 2, "expected at least 2 transitions, got {}", seq.len());
54+
let last = seq.last().and_then(|v| v.as_mapping());
55+
let last_status = last
56+
.and_then(|m| m.get("status"))
57+
.and_then(|v| v.as_str());
58+
assert_eq!(last_status, Some("complete"));
59+
} else {
60+
panic!("transitions should be a YAML sequence");
61+
}
4762
}
4863

4964
#[test]

rust/leanspec-core/src/parsers/frontmatter.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ impl FrontmatterParser {
272272
updates: &std::collections::HashMap<String, serde_yaml::Value>,
273273
) -> Result<String, ParseError> {
274274
let (mut frontmatter, body) = self.parse(content)?;
275+
let previous_status = frontmatter.status;
276+
let now = Utc::now();
275277

276278
// Apply updates
277279
for (key, value) in updates {
@@ -307,12 +309,25 @@ impl FrontmatterParser {
307309
}
308310
}
309311

312+
// Ensure created_at exists for velocity tracking
313+
if frontmatter.created_at.is_none() {
314+
frontmatter.created_at = Some(now);
315+
}
316+
310317
// Update timestamps
311-
frontmatter.updated_at = Some(Utc::now());
318+
frontmatter.updated_at = Some(now);
319+
320+
// Track status transitions
321+
if frontmatter.status != previous_status {
322+
frontmatter.transitions.push(StatusTransition {
323+
status: frontmatter.status,
324+
at: now,
325+
});
326+
}
312327

313328
// Set completed_at if status changed to complete
314329
if frontmatter.status == SpecStatus::Complete && frontmatter.completed_at.is_none() {
315-
frontmatter.completed_at = Some(Utc::now());
330+
frontmatter.completed_at = Some(now);
316331
}
317332

318333
Ok(self.stringify(&frontmatter, &body))

0 commit comments

Comments
 (0)