Install
$ agentstack add skill-lugassawan-swe-workbench-language-csharp ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
C# / .NET
.NET 8 project shape
- Prefer SDK-style projects with explicit
TargetFramework(net8.0) and shared defaults inDirectory.Build.props. - Keep nullable reference types enabled for new code:
enable. - Use
ImplicitUsingswhen the repository already does; avoid hand-maintaining noisy common imports. - Keep application, domain, infrastructure, and test projects separate when boundaries are real, not just for ceremony.
net8.0
enable
enable
Nullable reference types
- Treat warnings as design feedback, not noise. Model absence with
T?,required, or a domain type. - Validate nullable inputs at boundaries; keep internals non-null where possible.
- Use
ArgumentNullException.ThrowIfNull(value)for guard clauses. - Avoid
!except when bridging a framework or serializer limitation; leave a short reason.
public sealed class User
{
public required string Email { get; init; }
public string? DisplayName { get; init; }
}
Records and value semantics
- Use
recordorreadonly record structfor immutable value-like data. - Use classes for identity, lifecycle, mutation, or behavior-heavy objects.
- Be deliberate with
with: it is copy-with-change, not validation unless constructors enforce invariants.
public sealed record Money(decimal Amount, string Currency);
var discounted = price with { Amount = price.Amount * 0.9m };
Pattern matching
- Use patterns for shape-based branching, parsing, and closed domain states.
- Prefer switch expressions when every case returns a value.
- Keep guards (
when) simple; complex decisions deserve named methods.
return command switch
{
CreateUser(var email) when email.Contains('@') => Create(email),
DeleteUser(var id) => Delete(id),
_ => throw new InvalidOperationException("unsupported command")
};
Async and cancellation
- Use
async/awaitall the way. Avoid.Result,.Wait(), and blocking over async work. - Accept and pass
CancellationTokenthrough I/O, database, and long-running operations. - In libraries, use
ConfigureAwait(false)when code does not need a captured context; in modern app code, follow the repo's convention. - Prefer
Task.WhenAllfor independent work; avoid unobserved fire-and-forget tasks.
public async Task GetUserAsync(string id, CancellationToken cancellationToken)
{
ArgumentException.ThrowIfNullOrWhiteSpace(id);
return await repository.FindAsync(id, cancellationToken).ConfigureAwait(false)
?? throw new UserNotFoundException(id);
}
Dependency injection and options
- Depend on abstractions at boundaries, but do not create interfaces for every class by habit.
- Use constructor injection for required collaborators; avoid service locator patterns.
- Bind configuration to option records and consume
IOptions,IOptionsSnapshot, orIOptionsMonitorbased on lifetime needs. - Validate options at startup when invalid configuration should fail fast.
public sealed record RetryOptions
{
public int MaxAttempts { get; init; } = 3;
}
public sealed class Worker(IOptions options)
{
private readonly RetryOptions retry = options.Value;
}
LINQ and performance
- Use LINQ for clear transformations, filtering, grouping, and projections.
- Prefer
Any()overCount() > 0, and avoid repeated enumeration of deferred queries. - In hot paths, benchmark before replacing readable LINQ with loops.
- Use
Span, pooling, and allocation-aware APIs only when profiling shows they matter.
var activeEmails = users
.Where(user => user.IsActive)
.Select(user => user.Email)
.ToArray();
Tooling
- Imports/Format:
dotnet format - Lint: Roslyn analyzers (
truein csproj);dotnet format --verify-no-changesas formatting gate in CI - Test:
dotnet test(see Testing below)
Testing
- xUnit, NUnit, and MSTest are all fine; follow the repository's existing framework.
- Use fluent assertions when already present, and keep tests behavior-focused.
- Mock external boundaries, not records, value objects, or simple domain behavior.
Avoid
- Disabling nullable warnings instead of fixing the contract.
- Blocking on tasks with
.Result,.Wait(), orGetAwaiter().GetResult(). - Treating dependency injection as a reason to hide every constructor behind an interface.
- Rewriting clear LINQ into loops without a measured performance reason.
- Making ASP.NET conventions the default for non-web .NET code.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: lugassawan
- Source: lugassawan/swe-workbench
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.