story-kit: start 72_bug_story_creation_does_not_quote_yaml_special_characters_in_name
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
# Bug 72: Story creation does not quote YAML special characters in name
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
The create_story MCP tool writes the name value into YAML front matter without quoting. If the name contains YAML-special characters like colons, the resulting front matter is invalid YAML and fails to parse.
|
||||||
|
|
||||||
|
## How to Reproduce
|
||||||
|
|
||||||
|
1. Call create_story with a name containing a colon, e.g. "Server-owned agent completion: remove report_completion dependency"
|
||||||
|
2. Open the generated .md file
|
||||||
|
3. Observe the front matter parser rejects it
|
||||||
|
|
||||||
|
## Actual Result
|
||||||
|
|
||||||
|
Invalid front matter: mapping values are not allowed in this context
|
||||||
|
|
||||||
|
## Expected Result
|
||||||
|
|
||||||
|
The name value should be quoted in the front matter so special characters are safe, e.g. name: "My story: with colons"
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
- [ ] Bug is fixed and verified
|
||||||
@@ -164,7 +164,7 @@ pub fn create_story_file(
|
|||||||
|
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
content.push_str("---\n");
|
content.push_str("---\n");
|
||||||
content.push_str(&format!("name: {name}\n"));
|
content.push_str(&format!("name: \"{}\"\n", name.replace('"', "\\\"")));
|
||||||
content.push_str("test_plan: pending\n");
|
content.push_str("test_plan: pending\n");
|
||||||
content.push_str("---\n\n");
|
content.push_str("---\n\n");
|
||||||
content.push_str(&format!("# Story {story_number}: {name}\n\n"));
|
content.push_str(&format!("# Story {story_number}: {name}\n\n"));
|
||||||
@@ -917,7 +917,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
content.push_str("---\n");
|
content.push_str("---\n");
|
||||||
content.push_str("name: My New Feature\n");
|
content.push_str("name: \"My New Feature\"\n");
|
||||||
content.push_str("test_plan: pending\n");
|
content.push_str("test_plan: pending\n");
|
||||||
content.push_str("---\n\n");
|
content.push_str("---\n\n");
|
||||||
content.push_str(&format!("# Story {number}: My New Feature\n\n"));
|
content.push_str(&format!("# Story {number}: My New Feature\n\n"));
|
||||||
@@ -932,13 +932,29 @@ mod tests {
|
|||||||
fs::write(&filepath, &content).unwrap();
|
fs::write(&filepath, &content).unwrap();
|
||||||
|
|
||||||
let written = fs::read_to_string(&filepath).unwrap();
|
let written = fs::read_to_string(&filepath).unwrap();
|
||||||
assert!(written.starts_with("---\nname: My New Feature\ntest_plan: pending\n---"));
|
assert!(written.starts_with("---\nname: \"My New Feature\"\ntest_plan: pending\n---"));
|
||||||
assert!(written.contains("# Story 37: My New Feature"));
|
assert!(written.contains("# Story 37: My New Feature"));
|
||||||
assert!(written.contains("- [ ] It works"));
|
assert!(written.contains("- [ ] It works"));
|
||||||
assert!(written.contains("- [ ] It is tested"));
|
assert!(written.contains("- [ ] It is tested"));
|
||||||
assert!(written.contains("## Out of Scope"));
|
assert!(written.contains("## Out of Scope"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_story_with_colon_in_name_produces_valid_yaml() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let name = "Server-owned agent completion: remove report_completion dependency";
|
||||||
|
let result = create_story_file(tmp.path(), name, None, None, false);
|
||||||
|
assert!(result.is_ok(), "create_story_file failed: {result:?}");
|
||||||
|
|
||||||
|
let upcoming = tmp.path().join(".story_kit/work/1_upcoming");
|
||||||
|
let story_id = result.unwrap();
|
||||||
|
let filename = format!("{story_id}.md");
|
||||||
|
let contents = fs::read_to_string(upcoming.join(&filename)).unwrap();
|
||||||
|
|
||||||
|
let meta = parse_front_matter(&contents).expect("front matter should be valid YAML");
|
||||||
|
assert_eq!(meta.name.as_deref(), Some(name));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_story_rejects_duplicate() {
|
fn create_story_rejects_duplicate() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user