Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
dcd8af4
fix: the async idle state detection logic was reconsidered; some opti…
Feb 20, 2026
89fd40f
docs: improve documentation for last execution request tracking in Re…
Feb 20, 2026
4d90eb2
refactor: refactor test diagnostics initialization to use readonly fi…
Feb 20, 2026
c0be65e
todo: add TODO comments outlining planned improvements and refactorin…
Feb 20, 2026
a52d085
docs: agent guidelines for SlidingWindowCache have been added with ar…
Feb 21, 2026
8c9a0a5
docs: exception testing examples to AGENTS.md for improved clarity on…
Feb 21, 2026
9ffa2e9
feat: implement disposal pattern for WindowCache to ensure resource m…
Feb 21, 2026
3be9fde
docs: correct threading model documentation across codebase
Feb 21, 2026
6dabf63
refactor: code clarity by removing redundant whitespace and enhancing…
Feb 21, 2026
84b515c
refactor: execution controller interface has been introduced for reba…
Feb 21, 2026
bb9d239
refactor(concurrency model): improve clarity and detail of concurrenc…
Feb 21, 2026
e6bd301
chore: not used DTO has been removed
Feb 21, 2026
37be8d1
docs: update invariants documentation to include activity tracking an…
Feb 21, 2026
b039a29
feat(docs): add diagnostics documentation for cache behavior events;
Feb 22, 2026
e702970
docs: update architectural documentation for clarity and accuracy;
Feb 22, 2026
da42563
feat(tests): enhance test coverage with new gap tests and parameteriz…
Feb 22, 2026
28d5f22
docs: README and WasmCompilationValidator have been updated to includ…
Feb 22, 2026
82fd028
docs: glossary document has been added to define technical terms used…
Feb 22, 2026
304061f
fix: NoRebalanceRange planner logic was fixed taking into account tha…
Feb 22, 2026
6c3c8bb
feat(benchmark): add execution strategy benchmarks for unbounded and …
Feb 22, 2026
52311b9
refactor: data generation logic for range has been improved to respec…
Feb 23, 2026
6885465
refactor(concurrency): enhance async disposal coordination using Task…
Feb 23, 2026
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
375 changes: 375 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,375 @@
# Agent Guidelines for SlidingWindowCache

This document provides essential information for AI coding agents working on the SlidingWindowCache codebase.

## Project Overview

**SlidingWindowCache** is a C# .NET 8.0 library implementing a read-only, range-based, sequential-optimized cache with decision-driven background rebalancing. This is a production-ready concurrent systems project with extensive architectural documentation.

**Key Architecture Principles:**
- Single-Writer Architecture: Only rebalance execution mutates cache state
- Decision-Driven Execution: Multi-stage validation prevents thrashing
- Smart Eventual Consistency: Converges to optimal state while avoiding unnecessary work
- Fully Lock-Free Concurrency: Volatile/Interlocked operations, including fully lock-free AsyncActivityCounter
- User Path Priority: User requests never block on rebalance operations

## Build Commands

### Prerequisites
- .NET SDK 8.0 (specified in `global.json`)

### Common Build Commands
```bash
# Restore dependencies
dotnet restore SlidingWindowCache.sln

# Build solution (Debug)
dotnet build SlidingWindowCache.sln

# Build solution (Release)
dotnet build SlidingWindowCache.sln --configuration Release

# Build specific project
dotnet build src/SlidingWindowCache/SlidingWindowCache.csproj --configuration Release

# Pack for NuGet
dotnet pack src/SlidingWindowCache/SlidingWindowCache.csproj --configuration Release --output ./artifacts
```

## Test Commands

### Test Framework: xUnit 2.5.3

```bash
# Run all tests
dotnet test SlidingWindowCache.sln --configuration Release

# Run specific test project
dotnet test tests/SlidingWindowCache.Unit.Tests/SlidingWindowCache.Unit.Tests.csproj
dotnet test tests/SlidingWindowCache.Integration.Tests/SlidingWindowCache.Integration.Tests.csproj
dotnet test tests/SlidingWindowCache.Invariants.Tests/SlidingWindowCache.Invariants.Tests.csproj

# Run single test by fully qualified name
dotnet test --filter "FullyQualifiedName=SlidingWindowCache.Unit.Tests.Public.Configuration.WindowCacheOptionsTests.Constructor_WithValidParameters_InitializesAllProperties"

# Run tests matching pattern
dotnet test --filter "FullyQualifiedName~Constructor"

# Run with code coverage
dotnet test --collect:"XPlat Code Coverage" --results-directory ./TestResults
```

**Test Projects:**
- **Unit Tests**: Individual component testing with Moq 4.20.70
- **Integration Tests**: Component interaction, concurrency, data source interaction
- **Invariants Tests**: 27 automated tests validating architectural contracts via public API

## Linting & Formatting

**No explicit linting tools configured.** The codebase relies on:
- Visual Studio/Rider defaults
- Nullable reference types enabled (`<Nullable>enable</Nullable>`)
- Implicit usings enabled (`<ImplicitUsings>enable</ImplicitUsings>`)
- C# 12 language features

## Code Style Guidelines

### Namespace Organization
```csharp
// Use file-scoped namespace declarations (C# 10+)
namespace SlidingWindowCache.Public;
namespace SlidingWindowCache.Core.UserPath;
namespace SlidingWindowCache.Infrastructure.Storage;
```

**Namespace Structure:**
- `SlidingWindowCache.Public` - Public API surface
- `SlidingWindowCache.Core` - Business logic (internal)
- `SlidingWindowCache.Infrastructure` - Infrastructure concerns (internal)

### Naming Conventions

**Classes:**
- PascalCase with descriptive role/responsibility suffix
- Internal classes marked `internal sealed`
- Examples: `WindowCache`, `UserRequestHandler`, `RebalanceDecisionEngine`

**Interfaces:**
- IPascalCase prefix
- Examples: `IDataSource`, `ICacheDiagnostics`, `IWindowCache`

**Generic Type Parameters:**
- `TRange` - Range boundary type
- `TData` - Cached data type
- `TDomain` - Range domain type
- Use consistent generic names across entire codebase

**Fields:**
- Private readonly: `_fieldName` (underscore prefix)
- Examples: `_userRequestHandler`, `_cacheExtensionService`, `_state`

**Properties:**
- PascalCase: `LeftCacheSize`, `CurrentCacheRange`, `NoRebalanceRange`
- Use `init`/`set` appropriately for immutability

**Methods:**
- PascalCase with clear verb-noun structure
- Async methods ALWAYS end with `Async`
- Examples: `GetDataAsync`, `HandleRequestAsync`, `PublishIntent`

### Import Patterns

**Implicit Usings Enabled** - No need for `System.*` imports.

**Import Order:**
1. External libraries (e.g., `Intervals.NET`)
2. Project namespaces (e.g., `SlidingWindowCache.*`)
3. Alphabetically sorted within each group

**Example:**
```csharp
using Intervals.NET;
using Intervals.NET.Domain.Abstractions;
using SlidingWindowCache.Core.Planning;
using SlidingWindowCache.Core.State;
using SlidingWindowCache.Infrastructure.Instrumentation;
```

### XML Documentation

**Required for all public APIs:**
```csharp
/// <summary>
/// Brief description of the component/method.
/// </summary>
/// <typeparam name="TRange">Description of type parameter.</typeparam>
/// <param name="parameter">Description of parameter.</param>
/// <returns>Description of return value.</returns>
/// <remarks>
/// <para><strong>Architectural Context:</strong></para>
/// <para>Detailed remarks with bullet points...</para>
/// <list type="bullet">
/// <item><description>First point</description></item>
/// </list>
/// </remarks>
```

**Internal components should have detailed architectural remarks:**
- References to invariants (see `docs/invariants.md`)
- Cross-references to related components
- Explicit responsibilities and non-responsibilities
- Execution context (User Thread vs Background Thread)

### Type Guidelines

**Use appropriate types:**
- `ReadOnlyMemory<T>` for data buffers
- `ValueTask<T>` for frequently-called async methods
- `Task` for less frequent async operations
- `record` types for immutable configuration/DTOs
- `sealed` for classes that shouldn't be inherited

**Validation:**
```csharp
// Constructor validation with descriptive exceptions
if (leftCacheSize < 0)
{
throw new ArgumentOutOfRangeException(
nameof(leftCacheSize),
"LeftCacheSize must be greater than or equal to 0."
);
}
```

### Error Handling

**User Path Exceptions:**
- Propagate exceptions to caller
- Use descriptive exception messages
- Validate parameters early

**Background Path Exceptions:**
```csharp
// Fire-and-forget with diagnostics callback
try
{
// Rebalance execution
}
catch (Exception ex)
{
_cacheDiagnostics.RebalanceExecutionFailed(ex);
// Exception swallowed to prevent background task crashes
}
```

**Critical Rule:** Background exceptions must NOT crash the application. Always capture and report via diagnostics interface.

### Concurrency Patterns

**Single-Writer Architecture (CRITICAL):**
- User Path: READ-ONLY (never mutates Cache, LastRequested, or NoRebalanceRange)
- Rebalance Execution: SINGLE WRITER (sole authority for cache mutations)
- Serialization: Channel-based with single reader/single writer (intent processing loop)

**Threading Model - Single Logical Consumer with Internal Concurrency:**
- **User-facing model**: One logical consumer per cache (one user, one viewport, coherent access pattern)
- **Internal implementation**: Multiple threads operate concurrently (User thread + Intent loop + Execution loop)
- WindowCache **IS thread-safe** for its internal concurrency (user thread + background threads)
- WindowCache is **NOT designed for multiple users sharing one cache** (violates coherent access pattern)
- Multiple threads from the SAME logical consumer CAN call WindowCache safely (read-only User Path)

**Lock-Free Operations:**
```csharp
// Intent management using Volatile and Interlocked
var previousIntent = Interlocked.Exchange(ref _currentIntent, newIntent);
var currentIntent = Volatile.Read(ref _currentIntent);

// AsyncActivityCounter - fully lock-free as of latest refactor
var newCount = Interlocked.Increment(ref _activityCount); // Atomic counter
Volatile.Write(ref _idleTcs, newTcs); // Publish TCS with release fence
var tcs = Volatile.Read(ref _idleTcs); // Observe TCS with acquire fence
```

**Note**: AsyncActivityCounter is now fully lock-free (refactored from previous lock-based implementation).

### Testing Guidelines

**Test Structure:**
- Use xUnit `[Fact]` and `[Theory]` attributes
- Follow Arrange-Act-Assert pattern
- Use region comments: `#region Constructor - Valid Parameters Tests`

**Test Naming:**
```csharp
[Fact]
public void MethodName_Scenario_ExpectedBehavior()
{
// ARRANGE
var options = new WindowCacheOptions(...);

// ACT
var result = options.DoSomething();

// ASSERT
Assert.Equal(expectedValue, result);
}
```

**Exception Testing:**
```csharp
// Use Record.Exception/ExceptionAsync to separate ACT from ASSERT
var exception = Record.Exception(() => operation());
var exceptionAsync = await Record.ExceptionAsync(async () => await operationAsync());

Assert.NotNull(exception); // Verify exception thrown
Assert.IsType<ArgumentException>(exception); // Verify type
Assert.Null(exception); // Verify no exception
```

**WaitForIdleAsync Usage:**
```csharp
// Use for testing to wait until system was idle at some point
await cache.WaitForIdleAsync();

// Cache WAS idle (converged state) - assert on that state
Assert.Equal(expectedRange, actualRange);
```

**WaitForIdleAsync Semantics:**
- Completes when system **was idle at some point** (not "is idle now")
- Uses eventual consistency semantics (correct for testing convergence)
- New activity may start immediately after completion
- Re-check state if stronger guarantees needed

**When WaitForIdleAsync is NOT needed**: After normal `GetDataAsync` calls (cache is eventually consistent by design).

## Commit & Documentation Workflow

### Commit Message Guidelines
- **Format**: Conventional Commits with passive voice
- **Tool**: GitHub Copilot generates commit messages
- **Multi-type commits allowed**: Combine feat/test/docs/fix in single commit

**Examples:**
```
feat: extension method for strong consistency mode has been implemented; test: new method has been covered by unit tests; docs: README.md has been updated with usage examples

fix: race condition in intent processing has been resolved

refactor: AsyncActivityCounter lock has been removed and replaced with lock-free mechanism
```

### Documentation Philosophy
- **Code is source of truth** - documentation follows code
- **CRITICAL**: Every implementation MUST be finalized by updating documentation
- Documentation may be outdated; long-term goal is synchronization with code

### Documentation Update Map
| File | Update When | Focus |
|------|-------------|-------|
| `README.md` | Public API changes, new features | User-facing examples, configuration |
| `docs/invariants.md` | Architectural invariants changed | System constraints, concurrency rules |
| `docs/architecture-model.md` | Concurrency mechanisms changed | Thread safety, synchronization primitives |
| `docs/component-map.md` | New components, major refactoring | Component catalog, dependencies |
| `docs/actors-and-responsibilities.md` | Component responsibilities changed | Actor roles, explicit responsibilities |
| `docs/cache-state-machine.md` | State transitions changed | State machine specification |
| `docs/storage-strategies.md` | Storage implementation changed | Strategy comparison, performance |
| `docs/scenario-model.md` | Temporal behavior changed | Scenario walkthroughs, sequences |
| `docs/diagnostics.md` | New diagnostics events | Instrumentation guide |
| `benchmarks/*/README.md` | Benchmark changes | Performance methodology, results |
| `tests/*/README.md` | Test architecture changes | Test suite documentation |
| XML comments (in code) | All code changes | Component purpose, invariant references |

## Architecture References

**Before making changes, consult these critical documents:**
- `docs/invariants.md` - System invariants (33KB) - READ THIS FIRST
- `docs/architecture-model.md` - Architecture and concurrency model
- `docs/actors-and-responsibilities.md` - Component responsibilities
- `docs/component-map.md` - Detailed component catalog (86KB)
Comment thread
blaze6950 marked this conversation as resolved.
- `README.md` - User guide and examples (32KB)

**Key Invariants to NEVER violate:**
1. Cache Contiguity: No gaps allowed in cached ranges
2. Single Writer: Only RebalanceExecutor mutates cache state
3. User Path Priority: User requests never block on rebalance
4. Intent Semantics: Intents are signals, not commands
5. Decision Idempotency: Same inputs → same decision

## File Locations

**Public API:**
- `src/SlidingWindowCache/Public/WindowCache.cs` - Main cache facade
- `src/SlidingWindowCache/Public/IDataSource.cs` - Data source contract
- `src/SlidingWindowCache/Public/Configuration/` - Configuration classes

**Core Logic:**
- `src/SlidingWindowCache/Core/UserPath/` - User request handling (read-only)
- `src/SlidingWindowCache/Core/Rebalance/Decision/` - Decision engine
- `src/SlidingWindowCache/Core/Rebalance/Execution/` - Cache mutations (single writer)
- `src/SlidingWindowCache/Core/State/` - State management

**Infrastructure:**
- `src/SlidingWindowCache/Infrastructure/Storage/` - Storage strategies
- `src/SlidingWindowCache/Infrastructure/Instrumentation/` - Diagnostics
- `src/SlidingWindowCache/Infrastructure/Concurrency/` - Async coordination

## CI/CD

**GitHub Actions:** `.github/workflows/slidingwindowcache.yml`
- Triggers: Push/PR to main/master, manual dispatch
- Runs: Build, WebAssembly validation, all test suites with coverage
- Coverage: Uploaded to Codecov
- Publish: NuGet.org (on main/master push)

**Local CI Testing:**
```powershell
.github/test-ci-locally.ps1
```

## Important Notes

- **WebAssembly Compatible:** Validated with `net8.0-browser` target
- **Zero Dependencies (runtime):** Only `Intervals.NET.*` packages
- **Deterministic Testing:** Use `WaitForIdleAsync()` for predictable test behavior
- **Immutability:** Prefer `record` types and `init` properties for configuration
Loading