Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/agents/code-quality-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
Expand Down
17 changes: 17 additions & 0 deletions .github/agents/requirements-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions .github/agents/test-developer.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions src/DemaConsulting.SarifMark/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ private Context()
/// <exception cref="ArgumentException">Thrown when arguments are invalid.</exception>
public static Context Create(string[] args)
{
// Validate input
ArgumentNullException.ThrowIfNull(args);

var parser = new ArgumentParser();
parser.ParseArguments(args);

Expand Down Expand Up @@ -216,6 +219,9 @@ private sealed class ArgumentParser
/// <param name="args">Command-line arguments.</param>
public void ParseArguments(string[] args)
{
// Validate input
ArgumentNullException.ThrowIfNull(args);

int i = 0;
while (i < args.Length)
{
Expand Down
17 changes: 14 additions & 3 deletions src/DemaConsulting.SarifMark/DemaConsulting.SarifMark.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<LangVersion>12</LangVersion>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

Expand Down Expand Up @@ -34,7 +34,7 @@

<!-- Code Quality Configuration -->
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<AnalysisLevel>latest</AnalysisLevel>
Expand All @@ -48,13 +48,24 @@

<ItemGroup>
<PackageReference Include="DemaConsulting.TestResults" Version="1.5.0" />
<!-- PrivateAssets="All" prevents these build-time-only packages from becoming transitive dependencies -->
<PackageReference Include="Microsoft.Sbom.Targets" Version="4.1.5" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.103" PrivateAssets="All" />
<!--
Analyzer and source-only packages require both PrivateAssets and IncludeAssets:
PrivateAssets="all" - prevents these build-time assets from flowing to consumers
IncludeAssets - explicitly enables contentfiles (source injection) and
analyzers/buildtransitive (Roslyn analyzers at compile time)
-->
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.103">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.19.0.132793">
<PackageReference Include="Polyfill" Version="9.12.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.20.0.135146">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
3 changes: 3 additions & 0 deletions src/DemaConsulting.SarifMark/Validation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ internal static class Validation
/// <param name="context">The context containing command line arguments and program state.</param>
public static void Run(Context context)
{
// Validate input
ArgumentNullException.ThrowIfNull(context);

// Print validation header
PrintValidationHeader(context);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
<PropertyGroup>
<!-- Build Configuration -->
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<LangVersion>12</LangVersion>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<GenerateDocumentationFile>true</GenerateDocumentationFile>

<!-- Code Quality Configuration -->
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand All @@ -18,13 +18,18 @@
<AnalysisLevel>latest</AnalysisLevel>
</PropertyGroup>

<!-- Implicit Usings -->
<ItemGroup>
<Using Include="Polyfills" />
</ItemGroup>

<!-- Test Framework Dependencies -->
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="4.1.0" />
<PackageReference Include="MSTest.TestFramework" Version="4.1.0" />
</ItemGroup>
Expand All @@ -35,7 +40,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.19.0.132793">
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.20.0.135146">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down