diff --git a/.github/agents/code-quality-agent.md b/.github/agents/code-quality-agent.md
index 3e0ae21..ac9ea02 100644
--- a/.github/agents/code-quality-agent.md
+++ b/.github/agents/code-quality-agent.md
@@ -31,7 +31,7 @@ Ensure the project is:
1. **Build**: Zero warnings (TreatWarningsAsErrors=true)
2. **Linting**:
- - markdownlint (`.markdownlint.json`)
+ - markdownlint (`.markdownlint-cli2.jsonc`)
- cspell (`.cspell.json`)
- yamllint (`.yamllint.yaml`)
- dotnet format (`.editorconfig`)
diff --git a/.github/agents/requirements-agent.md b/.github/agents/requirements-agent.md
index de0b33f..6bfb689 100644
--- a/.github/agents/requirements-agent.md
+++ b/.github/agents/requirements-agent.md
@@ -49,6 +49,23 @@ Follow the `requirements.yaml` structure:
- Linked to appropriate test(s)
- Enforced via: `dotnet reqstream --requirements requirements.yaml --tests "test-results/**/*.trx" --enforce`
+### Test Source Filters
+
+Test links in `requirements.yaml` can include a source filter prefix to restrict which test results count as
+evidence. This is critical for platform and framework requirements - **never remove these filters**.
+
+- `windows@TestName` - proves the test passed on a Windows platform
+- `ubuntu@TestName` - proves the test passed on a Linux (Ubuntu) platform
+- `net8.0@TestName` - proves the test passed under the .NET 8 target framework
+- `net9.0@TestName` - proves the test passed under the .NET 9 target framework
+- `net10.0@TestName` - proves the test passed under the .NET 10 target framework
+- `dotnet8.x@TestName` - proves the self-validation test ran on a machine with .NET 8.x runtime
+- `dotnet9.x@TestName` - proves the self-validation test ran on a machine with .NET 9.x runtime
+- `dotnet10.x@TestName` - proves the self-validation test ran on a machine with .NET 10.x runtime
+
+Without the source filter, a test result from any platform/framework satisfies the requirement. Removing a
+filter invalidates the evidence for platform/framework requirements.
+
## Defer To
- **Software Developer Agent**: For implementing self-validation tests
diff --git a/.github/agents/test-developer.md b/.github/agents/test-developer.md
index 01c22d7..842a34a 100644
--- a/.github/agents/test-developer.md
+++ b/.github/agents/test-developer.md
@@ -123,6 +123,15 @@ Common anti-patterns to avoid (not exhaustive):
// ✅ Good: Assert.HasCount(3, collection);
```
+5. **Avoid Assert.IsTrue for string prefix checks** - Use `Assert.StartsWith` instead of wrapping
+ `string.StartsWith` in `Assert.IsTrue`, as it produces clearer failure messages that show the expected prefix
+ and actual value:
+
+ ```csharp
+ // ❌ Bad: Assert.IsTrue(value.StartsWith("prefix"));
+ // ✅ Good: Assert.StartsWith("prefix", value);
+ ```
+
## Defer To
- **Requirements Agent**: For test strategy and coverage requirements
diff --git a/AGENTS.md b/AGENTS.md
index 92db265..fc76d5f 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -27,6 +27,20 @@ Project-specific guidance for agents working on SarifMark - a .NET CLI tool for
- Enforced in CI: `dotnet reqstream --requirements requirements.yaml --tests "test-results/**/*.trx" --enforce`
- When adding features: add requirement + link to test
+## Test Source Filters
+
+Test links in `requirements.yaml` can include a source filter prefix to restrict which test results count as
+evidence. This is critical for platform and framework requirements - **do not remove these filters**.
+
+- `windows@TestName` - proves the test passed on a Windows platform
+- `ubuntu@TestName` - proves the test passed on a Linux (Ubuntu) platform
+- `net8.0@TestName` - proves the test passed under the .NET 8 target framework
+- `net9.0@TestName` - proves the test passed under the .NET 9 target framework
+- `net10.0@TestName` - proves the test passed under the .NET 10 target framework
+- `dotnet8.x@TestName` - proves the self-validation test ran on a machine with .NET 8.x runtime
+- `dotnet9.x@TestName` - proves the self-validation test ran on a machine with .NET 9.x runtime
+- `dotnet10.x@TestName` - proves the self-validation test ran on a machine with .NET 10.x runtime
+
## Testing (SarifMark-Specific)
- **Test Naming**: `ClassName_MethodUnderTest_Scenario_ExpectedBehavior` (for requirements traceability)
diff --git a/src/DemaConsulting.SarifMark/Context.cs b/src/DemaConsulting.SarifMark/Context.cs
index 3561540..0970452 100644
--- a/src/DemaConsulting.SarifMark/Context.cs
+++ b/src/DemaConsulting.SarifMark/Context.cs
@@ -105,6 +105,9 @@ private Context()
/// Thrown when arguments are invalid.
public static Context Create(string[] args)
{
+ // Validate input
+ ArgumentNullException.ThrowIfNull(args);
+
var parser = new ArgumentParser();
parser.ParseArguments(args);
@@ -216,6 +219,9 @@ private sealed class ArgumentParser
/// Command-line arguments.
public void ParseArguments(string[] args)
{
+ // Validate input
+ ArgumentNullException.ThrowIfNull(args);
+
int i = 0;
while (i < args.Length)
{
diff --git a/src/DemaConsulting.SarifMark/DemaConsulting.SarifMark.csproj b/src/DemaConsulting.SarifMark/DemaConsulting.SarifMark.csproj
index 4ff7e38..5c70bc9 100644
--- a/src/DemaConsulting.SarifMark/DemaConsulting.SarifMark.csproj
+++ b/src/DemaConsulting.SarifMark/DemaConsulting.SarifMark.csproj
@@ -3,7 +3,7 @@
Exe
net8.0;net9.0;net10.0
- 12
+ latest
enable
enable
@@ -34,7 +34,7 @@
true
- True
+ true
true
true
latest
@@ -48,13 +48,24 @@
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/DemaConsulting.SarifMark/Validation.cs b/src/DemaConsulting.SarifMark/Validation.cs
index 8ff1bca..f71ac75 100644
--- a/src/DemaConsulting.SarifMark/Validation.cs
+++ b/src/DemaConsulting.SarifMark/Validation.cs
@@ -34,6 +34,9 @@ internal static class Validation
/// The context containing command line arguments and program state.
public static void Run(Context context)
{
+ // Validate input
+ ArgumentNullException.ThrowIfNull(context);
+
// Print validation header
PrintValidationHeader(context);
diff --git a/test/DemaConsulting.SarifMark.Tests/DemaConsulting.SarifMark.Tests.csproj b/test/DemaConsulting.SarifMark.Tests/DemaConsulting.SarifMark.Tests.csproj
index 07aacbb..556048e 100644
--- a/test/DemaConsulting.SarifMark.Tests/DemaConsulting.SarifMark.Tests.csproj
+++ b/test/DemaConsulting.SarifMark.Tests/DemaConsulting.SarifMark.Tests.csproj
@@ -3,13 +3,13 @@
net8.0;net9.0;net10.0
- 12
+ latest
enable
enable
false
true
- True
+ true
true
@@ -18,13 +18,18 @@
latest
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
@@ -35,7 +40,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive