story-kit: merge 217_story_scaffold_generates_claude_md
This commit is contained in:
@@ -52,6 +52,14 @@ TODO: List approved libraries and their purpose.\n";
|
||||
|
||||
const STORY_KIT_SCRIPT_TEST: &str = "#!/usr/bin/env bash\nset -euo pipefail\n\n# Add your project's test commands here.\n# Story Kit agents invoke this script as the canonical test runner.\n# Exit 0 on success, non-zero on failure.\necho \"No tests configured\"\n";
|
||||
|
||||
const STORY_KIT_CLAUDE_MD: &str = "<!-- story-kit:scaffold-template -->\n\
|
||||
Never chain shell commands with `&&`, `||`, or `;` in a single Bash call. \
|
||||
The permission system validates the entire command string, and chained commands \
|
||||
won't match allow rules like `Bash(git *)`. Use separate Bash calls instead — \
|
||||
parallel calls work fine.\n\
|
||||
\n\
|
||||
Read .story_kit/README.md to see our dev process.\n";
|
||||
|
||||
const DEFAULT_PROJECT_TOML: &str = r#"[[agent]]
|
||||
name = "coder-1"
|
||||
stage = "coder"
|
||||
@@ -253,6 +261,7 @@ fn scaffold_story_kit(root: &Path) -> Result<(), String> {
|
||||
write_file_if_missing(&specs_root.join("00_CONTEXT.md"), STORY_KIT_CONTEXT)?;
|
||||
write_file_if_missing(&tech_root.join("STACK.md"), STORY_KIT_STACK)?;
|
||||
write_script_if_missing(&script_root.join("test"), STORY_KIT_SCRIPT_TEST)?;
|
||||
write_file_if_missing(&root.join("CLAUDE.md"), STORY_KIT_CLAUDE_MD)?;
|
||||
|
||||
append_gitignore_entries(root)?;
|
||||
|
||||
@@ -268,7 +277,7 @@ fn scaffold_story_kit(root: &Path) -> Result<(), String> {
|
||||
}
|
||||
|
||||
let add_output = std::process::Command::new("git")
|
||||
.args(["add", ".story_kit", "script", ".gitignore"])
|
||||
.args(["add", ".story_kit", "script", ".gitignore", "CLAUDE.md"])
|
||||
.current_dir(root)
|
||||
.output()
|
||||
.map_err(|e| format!("Failed to run git add: {}", e))?;
|
||||
@@ -1074,6 +1083,46 @@ mod tests {
|
||||
assert!(content.contains("store.json"));
|
||||
}
|
||||
|
||||
// --- CLAUDE.md scaffold ---
|
||||
|
||||
#[test]
|
||||
fn scaffold_creates_claude_md_at_project_root() {
|
||||
let dir = tempdir().unwrap();
|
||||
scaffold_story_kit(dir.path()).unwrap();
|
||||
|
||||
let claude_md = dir.path().join("CLAUDE.md");
|
||||
assert!(claude_md.exists(), "CLAUDE.md should be created at project root");
|
||||
|
||||
let content = fs::read_to_string(&claude_md).unwrap();
|
||||
assert!(
|
||||
content.contains("<!-- story-kit:scaffold-template -->"),
|
||||
"CLAUDE.md should contain the scaffold sentinel"
|
||||
);
|
||||
assert!(
|
||||
content.contains("Read .story_kit/README.md"),
|
||||
"CLAUDE.md should include directive to read .story_kit/README.md"
|
||||
);
|
||||
assert!(
|
||||
content.contains("Never chain shell commands"),
|
||||
"CLAUDE.md should include command chaining rule"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scaffold_does_not_overwrite_existing_claude_md() {
|
||||
let dir = tempdir().unwrap();
|
||||
let claude_md = dir.path().join("CLAUDE.md");
|
||||
fs::write(&claude_md, "custom CLAUDE.md content").unwrap();
|
||||
|
||||
scaffold_story_kit(dir.path()).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
fs::read_to_string(&claude_md).unwrap(),
|
||||
"custom CLAUDE.md content",
|
||||
"scaffold should not overwrite an existing CLAUDE.md"
|
||||
);
|
||||
}
|
||||
|
||||
// --- open_project scaffolding ---
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
Reference in New Issue
Block a user