Skip to content

Commit 87575bd

Browse files
zixlin7kennvene-aws
authored andcommitted
add support for always inclusion steering files (#3047)
1 parent 26caae9 commit 87575bd

File tree

5 files changed

+117
-1
lines changed

5 files changed

+117
-1
lines changed

Cargo.lock

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ jsonschema = "0.30.0"
134134
zip = "2.2.0"
135135
rmcp = { version = "0.8.0", features = ["client", "transport-sse-client-reqwest", "reqwest", "transport-streamable-http-client-reqwest", "transport-child-process", "tower", "auth"] }
136136
chat-cli-ui = { path = "crates/chat-cli-ui" }
137+
serde_yaml = "0.9"
137138

138139
[workspace.lints.rust]
139140
future_incompatible = "warn"

crates/chat-cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ jsonschema.workspace = true
121121
zip.workspace = true
122122
rmcp.workspace = true
123123
chat-cli-ui.workspace = true
124+
serde_yaml.workspace = true
124125

125126
[target.'cfg(unix)'.dependencies]
126127
nix.workspace = true

crates/chat-cli/src/cli/agent/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ impl Default for Agent {
195195
"file://AGENTS.md",
196196
"file://README.md",
197197
"file://.amazonq/rules/**/*.md",
198+
"file://.kiro/steering/**/*.md",
198199
]
199200
.into_iter()
200201
.map(Into::into)

crates/chat-cli/src/cli/chat/context.rs

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ async fn process_path(
366366
///
367367
/// This method:
368368
/// 1. Reads the content of the file
369-
/// 2. Adds the (filename, content) pair to the context collection
369+
/// 2. Checks front matter inclusion rules for steering files
370+
/// 3. Adds the (filename, content) pair to the context collection if allowed
370371
///
371372
/// # Arguments
372373
/// * `path` - The path to the file
@@ -377,10 +378,71 @@ async fn process_path(
377378
async fn add_file_to_context(os: &Os, path: &Path, context_files: &mut Vec<(String, String)>) -> Result<()> {
378379
let filename = path.to_string_lossy().to_string();
379380
let content = os.fs.read_to_string(path).await?;
381+
382+
// Check if this is a steering file that needs front matter filtering
383+
if filename.contains(".kiro/steering") && filename.ends_with(".md") {
384+
if !should_include_steering_file(&content)? {
385+
return Ok(());
386+
}
387+
}
388+
380389
context_files.push((filename, content));
381390
Ok(())
382391
}
383392

393+
#[derive(Debug, Deserialize)]
394+
struct FrontMatter {
395+
inclusion: Option<String>,
396+
}
397+
398+
/// Check if a steering file should be included based on its front matter
399+
fn should_include_steering_file(content: &str) -> Result<bool> {
400+
// Check if file has YAML front matter
401+
if !content.starts_with("---\n") {
402+
// No front matter - include the file
403+
return Ok(true);
404+
}
405+
406+
// Find the end of the front matter
407+
let lines: Vec<&str> = content.lines().collect();
408+
let mut end_index = None;
409+
410+
for (i, line) in lines.iter().enumerate().skip(1) {
411+
if line.trim() == "---" {
412+
end_index = Some(i);
413+
break;
414+
}
415+
}
416+
417+
let end_index = match end_index {
418+
Some(idx) => idx,
419+
None => {
420+
// Malformed front matter - include the file
421+
return Ok(true);
422+
}
423+
};
424+
425+
// Extract and parse the front matter
426+
let front_matter_lines = &lines[1..end_index];
427+
let front_matter_yaml = front_matter_lines.join("\n");
428+
429+
match serde_yaml::from_str::<FrontMatter>(&front_matter_yaml) {
430+
Ok(front_matter) => {
431+
match front_matter.inclusion.as_deref() {
432+
Some("always") => Ok(true),
433+
Some("fileMatch") => Ok(false), // Exclude fileMatch files
434+
Some("manual") => Ok(false), // Exclude manual files
435+
None => Ok(true), // No inclusion field - include
436+
Some(_) => Ok(true), // Unknown inclusion value - include
437+
}
438+
}
439+
Err(_) => {
440+
// Failed to parse front matter - include the file
441+
Ok(true)
442+
}
443+
}
444+
}
445+
384446
#[cfg(test)]
385447
mod tests {
386448
use super::*;
@@ -458,4 +520,35 @@ mod tests {
458520
96_000
459521
);
460522
}
523+
524+
#[test]
525+
fn test_should_include_steering_file() {
526+
// Test file without front matter - should be included
527+
let content_no_frontmatter = "# Regular markdown file\nSome content here.";
528+
assert!(should_include_steering_file(content_no_frontmatter).unwrap());
529+
530+
// Test file with inclusion: always - should be included
531+
let content_always = "---\ninclusion: always\n---\n# Always included\nContent here.";
532+
assert!(should_include_steering_file(content_always).unwrap());
533+
534+
// Test file with inclusion: fileMatch - should be excluded
535+
let content_filematch = "---\ninclusion: fileMatch\n---\n# File match only\nContent here.";
536+
assert!(!should_include_steering_file(content_filematch).unwrap());
537+
538+
// Test file with inclusion: manual - should be excluded
539+
let content_manual = "---\ninclusion: manual\n---\n# Manual only\nContent here.";
540+
assert!(!should_include_steering_file(content_manual).unwrap());
541+
542+
// Test file with no inclusion field - should be included
543+
let content_no_inclusion = "---\ntitle: Some Title\n---\n# No inclusion field\nContent here.";
544+
assert!(should_include_steering_file(content_no_inclusion).unwrap());
545+
546+
// Test file with malformed front matter - should be included
547+
let content_malformed = "---\ninvalid yaml: [\n---\n# Malformed\nContent here.";
548+
assert!(should_include_steering_file(content_malformed).unwrap());
549+
550+
// Test file with incomplete front matter - should be included
551+
let content_incomplete = "---\ninclusion: always\n# Missing closing ---\nContent here.";
552+
assert!(should_include_steering_file(content_incomplete).unwrap());
553+
}
461554
}

0 commit comments

Comments
 (0)