Watcher ignores file changes under .story_kit/worktrees/
Prevents agent code edits in worktrees from being auto-committed to master. Only work item file moves in .story_kit/work/ trigger watcher commits. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -51,7 +51,19 @@ fn stage_metadata(stage: &str, item_id: &str) -> Option<(&'static str, String)>
|
|||||||
|
|
||||||
/// Return the pipeline stage name for a path if it is a `.md` file living
|
/// Return the pipeline stage name for a path if it is a `.md` file living
|
||||||
/// directly inside one of the known work subdirectories, otherwise `None`.
|
/// directly inside one of the known work subdirectories, otherwise `None`.
|
||||||
|
///
|
||||||
|
/// Explicitly returns `None` for any path under `.story_kit/worktrees/` so
|
||||||
|
/// that code changes made by agents in their isolated worktrees are never
|
||||||
|
/// auto-committed to master by the watcher.
|
||||||
fn stage_for_path(path: &Path) -> Option<String> {
|
fn stage_for_path(path: &Path) -> Option<String> {
|
||||||
|
// Reject any path that passes through the worktrees directory.
|
||||||
|
if path
|
||||||
|
.components()
|
||||||
|
.any(|c| c.as_os_str() == "worktrees")
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
if path.extension().is_none_or(|e| e != "md") {
|
if path.extension().is_none_or(|e| e != "md") {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -267,6 +279,31 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn stage_for_path_ignores_worktree_paths() {
|
||||||
|
let worktrees = PathBuf::from("/proj/.story_kit/worktrees");
|
||||||
|
|
||||||
|
// Code changes inside a worktree must be ignored.
|
||||||
|
assert_eq!(
|
||||||
|
stage_for_path(&worktrees.join("42_story_foo/server/src/main.rs")),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Even if a worktree happens to contain a path component that looks
|
||||||
|
// like a pipeline stage, it must still be ignored.
|
||||||
|
assert_eq!(
|
||||||
|
stage_for_path(&worktrees.join("42_story_foo/.story_kit/work/2_current/42_story_foo.md")),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
// A path that only contains the word "worktrees" as part of a longer
|
||||||
|
// segment (not an exact component) must NOT be filtered out.
|
||||||
|
assert_eq!(
|
||||||
|
stage_for_path(&PathBuf::from("/proj/.story_kit/work/2_current/not_worktrees_story.md")),
|
||||||
|
Some("2_current".to_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn stage_metadata_returns_correct_actions() {
|
fn stage_metadata_returns_correct_actions() {
|
||||||
let (action, msg) = stage_metadata("2_current", "42_story_foo").unwrap();
|
let (action, msg) = stage_metadata("2_current", "42_story_foo").unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user