Skip to content

Commit 234cb92

Browse files
authored
add support for always inclusion steering files (aws#3047)
1 parent c9d6266 commit 234cb92

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
@@ -129,6 +129,7 @@ winnow = "=0.6.2"
129129
winreg = "0.55.0"
130130
schemars = "1.0.4"
131131
jsonschema = "0.30.0"
132+
serde_yaml = "0.9"
132133
rmcp = { version = "0.7.0", features = ["client", "transport-sse-client-reqwest", "reqwest", "transport-streamable-http-client-reqwest", "transport-child-process", "tower", "auth"] }
133134

134135
[workspace.lints.rust]

crates/chat-cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ winnow.workspace = true
118118
schemars.workspace = true
119119
jsonschema.workspace = true
120120
rmcp.workspace = true
121+
serde_yaml.workspace = true
121122

122123
[target.'cfg(unix)'.dependencies]
123124
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
@@ -189,6 +189,7 @@ impl Default for Agent {
189189
"file://AGENTS.md",
190190
"file://README.md",
191191
"file://.amazonq/rules/**/*.md",
192+
"file://.kiro/steering/**/*.md",
192193
]
193194
.into_iter()
194195
.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
@@ -367,7 +367,8 @@ async fn process_path(
367367
///
368368
/// This method:
369369
/// 1. Reads the content of the file
370-
/// 2. Adds the (filename, content) pair to the context collection
370+
/// 2. Checks front matter inclusion rules for steering files
371+
/// 3. Adds the (filename, content) pair to the context collection if allowed
371372
///
372373
/// # Arguments
373374
/// * `path` - The path to the file
@@ -378,10 +379,71 @@ async fn process_path(
378379
async fn add_file_to_context(os: &Os, path: &Path, context_files: &mut Vec<(String, String)>) -> Result<()> {
379380
let filename = path.to_string_lossy().to_string();
380381
let content = os.fs.read_to_string(path).await?;
382+
383+
// Check if this is a steering file that needs front matter filtering
384+
if filename.contains(".kiro/steering") && filename.ends_with(".md") {
385+
if !should_include_steering_file(&content)? {
386+
return Ok(());
387+
}
388+
}
389+
381390
context_files.push((filename, content));
382391
Ok(())
383392
}
384393

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

0 commit comments

Comments
 (0)