diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index c27a3dc..30e2b23 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -47,6 +47,24 @@ jobs: - name: Check dependency health run: python3 -m scripts.dependencies.check_package_health --solution ModularityKit.Mutator.slnx + docs: + name: docs + runs-on: ubuntu-latest + needs: build + + steps: + - uses: actions/checkout@v5 + + - uses: actions/setup-dotnet@v5 + with: + dotnet-version: 10.0.x + + - name: Install DocFX + run: dotnet tool update -g docfx + + - name: Build docs + run: docfx docfx.json + tests: name: ${{ matrix.name }} runs-on: ubuntu-latest @@ -177,6 +195,7 @@ jobs: needs: - build - dependency-health + - docs - tests - examples-core - examples-governance @@ -188,6 +207,7 @@ jobs: run: | echo "build: ${{ needs.build.result }}" echo "dependency-health: ${{ needs.dependency-health.result }}" + echo "docs: ${{ needs.docs.result }}" echo "tests: ${{ needs.tests.result }}" echo "examples-core: ${{ needs.examples-core.result }}" echo "examples-governance: ${{ needs.examples-governance.result }}" @@ -195,6 +215,7 @@ jobs: if [ "${{ needs.build.result }}" != "success" ] || \ [ "${{ needs.dependency-health.result }}" != "success" ] || \ + [ "${{ needs.docs.result }}" != "success" ] || \ [ "${{ needs.tests.result }}" != "success" ] || \ [ "${{ needs.examples-core.result }}" != "success" ] || \ [ "${{ needs.examples-governance.result }}" != "success" ] || \ diff --git a/.gitignore b/.gitignore index 48a9ed2..4d65f48 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .idea/ bin/ obj/ +_site/ __pycache__/ *.pyc diff --git a/Directory.Build.props b/Directory.Build.props index eefcd3d..7775afc 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - $(MSBuildProjectDirectory)/obj/$(MSBuildProjectName)/ + $(MSBuildThisFileDirectory)obj/$(MSBuildProjectName)/ diff --git a/Docs/API/API-Reference.md b/Docs/API/API-Reference.md deleted file mode 100644 index 53d7e9b..0000000 --- a/Docs/API/API-Reference.md +++ /dev/null @@ -1,289 +0,0 @@ - -# API Reference - -Complete API documentation for **ModularityKit.Mutators**. - ---- - -## Table of Contents - -- [Interfaces](#interfaces) - - [IMutation](#imutation) - - [IMutationPolicy](#imutationpolicy) -- [Base Classes](#base-classes) - - [MutationInterceptorBase](#mutationinterceptorbase) -- [Related Types](#related-types) -- [DI Extension Methods](#di-extension-methods) - - [AddMutators](#addmutators) -- [Governance API](#governance-api) -- [Execution Semantics](#execution-semantics) -- [Best Practices](#best-practices) -- [Complete Examples](#complete-examples) - ---- - -## Interfaces - -### IMutation - -Represents a mutation operation on a state of type `TState`. - -**Namespace:** `ModularityKit.Mutators.Abstractions.Engine` - -```csharp -public interface IMutation -{ - MutationIntent Intent { get; } - MutationContext Context { get; } - - MutationResult Apply(TState state); - ValidationResult Validate(TState state); - MutationResult Simulate(TState state); -} -``` - -**Type Parameters** - -| Parameter | Description | -| --------- | ------------------------------------------ | -| `TState` | Type of the state the mutation operates on | - -**Properties** - -| Property | Type | Description | -| --------- | ----------------- | ------------------------------------------------------- | -| `Intent` | `MutationIntent` | Declarative description of the change (what & why) | -| `Context` | `MutationContext` | Metadata about execution (who, when, correlation, mode) | - -**Methods** - -|Method|Returns|Description| -|---|---|---| -|`Apply`|`MutationResult`|Applies the mutation, producing new state| -|`Validate`|`ValidationResult`|Checks preconditions without mutating| -|`Simulate`|`MutationResult`|Dry-run, behaves like `Apply` but without persistence| - -**Semantics** - -- `Apply` must be deterministic given `(state, intent, context)` -- `Validate` must **never** mutate state or cause side-effects -- `Simulate` must match `Apply` behavior, except no persistence - ---- - -### IMutationPolicy - -Represents governance rule that can allow or block mutation. - -**Namespace:** `ModularityKit.Mutators.Abstractions.Policies` - -```csharp -public interface IMutationPolicy -{ - string Name { get; } - int Priority { get; } - string? Description { get; } - - PolicyDecision Evaluate(IMutation mutation, TState state); -} -``` - -**Type Parameters** - -|Parameter|Description| -|---|---| -|`TState`|State type the policy evaluates| - -**Properties** - -|Property|Type|Description| -|---|---|---| -|`Name`|`string`|Logical policy name| -|`Priority`|`int`|Evaluation order (higher runs first)| -|`Description`|`string?`|Optional description| - -**Method** - -|Method|Returns|Description| -|---|---|---| -|`Evaluate`|`PolicyDecision`|Determines if mutation is allowed| - -**Semantics** - -- Policies **must be deterministic and side effect free** -- Evaluated before mutation application -- Higher `Priority` runs earlier -- Any blocking decision cancels mutation - ---- - -## Base Classes - -### MutationInterceptorBase - -Base class for interceptors with default no-op implementations. - -**Namespace:** `ModularityKit.Mutators.Runtime.Interception` - -```csharp -public abstract class MutationInterceptorBase : IMutationInterceptor -{ - public virtual string Name { get; } - public virtual int Order { get; } - - protected internal virtual bool ShouldRun(MutationIntent intent, MutationContext context); - - public virtual Task OnBeforeMutationAsync( - MutationIntent intent, - MutationContext context, - object state, - string executionId, - CancellationToken cancellationToken = default); - - public virtual Task OnAfterMutationAsync( - MutationIntent intent, - MutationContext context, - object? oldState, - object? newState, - ChangeSet changes, - string executionId, - CancellationToken cancellationToken = default); - - public virtual Task OnMutationFailedAsync( - MutationIntent intent, - MutationContext context, - object state, - Exception exception, - string executionId, - CancellationToken cancellationToken = default); - - public virtual Task OnPolicyBlockedAsync( - MutationIntent intent, - MutationContext context, - object state, - PolicyDecision decision, - string executionId, - CancellationToken cancellationToken = default); -} -``` - -**Properties & Methods** - -| Member | Description | -| ----------------------- | ----------------------------------------------------- | -| `Name` | Logical interceptor name (default: type name) | -| `Order` | Execution order (low → high) | -| `ShouldRun` | Determines if interceptor executes for given mutation | -| `OnBeforeMutationAsync` | Hook before mutation | -| `OnAfterMutationAsync` | Hook after successful mutation | -| `OnMutationFailedAsync` | Hook on exception | -| `OnPolicyBlockedAsync` | Hook when mutation is blocked by policy | - -**Ordering Example** -``` -Order -100 → Infrastructure -Order 0 → Default -Order 100 → Diagnostics / Logging -``` - ---- - -## Related Types - -- `MutationIntent` — Declarative description of the change -- `MutationContext` — Metadata about execution -- `MutationResult` — Result of mutation application -- `ValidationResult` — Result of `Validate` -- `ChangeSet` — Detailed changes applied -- `PolicyDecision` — Allow/Block decision from policy - ---- - -## DI Extension Methods - -### AddMutators - -Registers Mutators framework in DI. - -**Namespace:** `ModularityKit.Mutators.Extensions` -```csharp -void AddMutators( - this IServiceCollection services, - MutationEngineOptions? presetOptions = null, - Action? configure = null, - bool addDefaultLoggingInterceptor = false) -``` - -**Parameters** - -|Parameter|Description| -|---|---| -|`services`|Target `IServiceCollection`| -|`presetOptions`|Optional base configuration| -|`configure`|Optional delegate for further configuration| -|`addDefaultLoggingInterceptor`|If `true`, registers default logging interceptor| - -**Registered Services** - -|Service|Implementation|Lifetime| -|---|---|---| -|`IMutationExecutor`|`MutationExecutor`|Singleton| -|`IPolicyRegistry`|`PolicyRegistry`|Singleton| -|`IInterceptorPipeline`|`InterceptorPipeline`|Singleton| -|`IMutationAuditor`|`InMemoryAuditor`|Singleton| -|`IMutationHistoryStore`|`InMemoryHistoryStore`|Singleton| -|`IMetricsCollector`|`MetricsCollectorImpl`|Singleton| -|`IMutationEngine`|`MutationEngine`|Singleton| - -**Example** -```csharp -services.AddMutators(MutationEngineOptions.Performance, addDefaultLoggingInterceptor: true); -``` - -**or** -```csharp -services.AddMutators(MutationEngineOptions.Strict, addDefaultLoggingInterceptor: true); -``` - ---- - -## Governance API - -Governance is documented separately so the core API reference can stay focused on direct mutation execution. - -- [Governance package overview](../../src/Governance/README.md) -- [Governance API usage](API.md) -- [Redis provider API](Redis.md) - -Governance-specific types such as `MutationRequestFactory`, `MutationRequestDecision`, and -`IGovernanceExecutionManager` live in the governance package, not the core mutation runtime. - ---- - -## Execution Semantics - -1. Call `Validate(state)` -2. Evaluate policies (`IMutationPolicy`) -3. Call interceptors `OnBeforeMutationAsync` -4. Apply mutation via `Apply(state)` -5. Call interceptors `OnAfterMutationAsync` -6. Emit results, metrics - -**Failure Paths** - -- Policy blocks → `OnPolicyBlockedAsync` -- Exception during apply → `OnMutationFailedAsync` - ---- - -## Best Practices - -- Mutations are **pure domain operations** (no I/O or side-effects) -- Policies are **side-effect free** -- Interceptors are **cross-cutting only**, never mutate state -- Use `Order` to explicitly control interceptor execution -- Prefer **many small interceptors** rather than a single large one - ---- - -> **Built with ❤️ for .NET developers** diff --git a/Docs/API/Redis.md b/Docs/API/Redis.md index ada25f1..5716b2b 100644 --- a/Docs/API/Redis.md +++ b/Docs/API/Redis.md @@ -132,5 +132,5 @@ in-memory provider. - [`src/Redis/README.md`](../../src/Redis/README.md) - [`Examples/Governance/RedisQueries/README.md`](../../Examples/Governance/RedisQueries/README.md) -- [`API-Reference.md`](API-Reference.md) +- [`Reference.md`](Reference.md) - [Governance API](API.md) diff --git a/Docs/API/Reference.md b/Docs/API/Reference.md new file mode 100644 index 0000000..177e261 --- /dev/null +++ b/Docs/API/Reference.md @@ -0,0 +1,18 @@ +# API Reference + +DocFX generates the public API reference from the compiled assemblies and XML documentation files. + +## Included packages + +- `ModularityKit.Mutator` +- `ModularityKit.Mutator.Governance` +- `ModularityKit.Mutator.Governance.Redis` + +## Build locally + +```bash +dotnet tool update -g docfx +docfx docfx.json +``` + +The rendered API pages appear under the `API` section of the generated site. diff --git a/README.md b/README.md index 0a27256..fad327b 100644 --- a/README.md +++ b/README.md @@ -36,3 +36,15 @@ python3 -m scripts.dependencies.check_package_health --solution ModularityKit.Mu ``` The check reports vulnerable packages as a failing condition and prints outdated packages for review. When a package needs attention, update the affected `PackageReference` version in the owning project and rerun the check. + +## Documentation + +Build the DocFX site locally with: + +```bash +dotnet tool update -g docfx +docfx docfx.json +``` + +The generated site includes the conceptual docs under `Docs/` and the public API reference for the +three published packages. diff --git a/docfx.json b/docfx.json new file mode 100644 index 0000000..e1d23bd --- /dev/null +++ b/docfx.json @@ -0,0 +1,69 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ + "src/ModularityKit.Mutator.csproj", + "src/ModularityKit.Mutator.Governance.csproj", + "src/Redis/ModularityKit.Mutator.Governance.Redis.csproj" + ], + "exclude": [ + "**/bin/**", + "**/obj/**" + ] + } + ], + "dest": "obj/api", + "properties": { + "Configuration": "Release", + "TargetFramework": "net10.0" + } + } + ], + "build": { + "content": [ + { + "files": [ + "README.md", + "toc.yml", + "Docs/**/*.md", + "src/**/README.md", + "Examples/**/README.md", + "Benchmarks/README.md" + ], + "exclude": [ + "**/bin/**", + "**/obj/**", + "**/_site/**" + ] + }, + { + "files": [ + "obj/api/**.yml", + "obj/api/**.md" + ] + } + ], + "resource": [ + { + "files": [ + "assets/**" + ], + "exclude": [ + "**/bin/**", + "**/obj/**" + ] + } + ], + "dest": "_site", + "globalMetadata": { + "_appTitle": "ModularityKit.Mutator", + "_appFooter": "ModularityKit.Mutator documentation", + "_enableSearch": true + }, + "template": [ + "default" + ] + } +} diff --git a/src/Abstractions/Engine/IMutationEngine.cs b/src/Abstractions/Engine/IMutationEngine.cs index 8f4b40e..db75f9a 100644 --- a/src/Abstractions/Engine/IMutationEngine.cs +++ b/src/Abstractions/Engine/IMutationEngine.cs @@ -26,7 +26,7 @@ namespace ModularityKit.Mutator.Abstractions.Engine; /// /// /// Core runtime concurrency is governed by . -/// Mutations that target the same are serialized by the runtime so shared-state workloads +/// Mutations that target the same are serialized by the runtime so shared-state workloads /// remain deterministic. This is separate from governance request storage concurrency, which protects request lifecycle writes /// in the governance package. /// @@ -78,7 +78,6 @@ Task> ExecuteBatchAsync( /// The type of the state being mutated. /// The initial state. /// The mutations to execute in order. - /// Token used to cancel execution. /// /// A describing the outcome of the batch execution. /// diff --git a/src/ModularityKit.Mutator.Governance.csproj b/src/ModularityKit.Mutator.Governance.csproj index fd73c51..a633472 100644 --- a/src/ModularityKit.Mutator.Governance.csproj +++ b/src/ModularityKit.Mutator.Governance.csproj @@ -4,6 +4,8 @@ net10.0 enable enable + true + $(NoWarn);1591 false ModularityKit.Mutator ModularityKit.Mutator.Governance diff --git a/src/ModularityKit.Mutator.csproj b/src/ModularityKit.Mutator.csproj index 35692b4..0000ca2 100644 --- a/src/ModularityKit.Mutator.csproj +++ b/src/ModularityKit.Mutator.csproj @@ -4,6 +4,8 @@ net10.0 enable enable + true + $(NoWarn);1591 ModularityKit.Mutator 0.1.0 ModularityKit diff --git a/src/Redis/ModularityKit.Mutator.Governance.Redis.csproj b/src/Redis/ModularityKit.Mutator.Governance.Redis.csproj index 0a9feb4..ba105e3 100644 --- a/src/Redis/ModularityKit.Mutator.Governance.Redis.csproj +++ b/src/Redis/ModularityKit.Mutator.Governance.Redis.csproj @@ -4,6 +4,8 @@ net10.0 enable enable + true + $(NoWarn);1591 ModularityKit.Mutator.Governance.Redis 0.1.0 ModularityKit diff --git a/src/Runtime/MutationExecutor.cs b/src/Runtime/MutationExecutor.cs index f8f3850..cd14edb 100644 --- a/src/Runtime/MutationExecutor.cs +++ b/src/Runtime/MutationExecutor.cs @@ -6,16 +6,13 @@ namespace ModularityKit.Mutator.Runtime; /// -/// Responsible for executing single mutation against given state. +/// Responsible for executing a single mutation against a given state. /// /// /// /// applies mutations in synchronous fashion (the -/// method is executed inline) while respecting timeouts and cancellation tokens provided via -/// and -/// cancellationToken -/// -/// . +/// method is executed inline) while respecting timeouts and cancellation tokens provided via the execution context and +/// the caller's cancellation token. /// /// /// This class does not perform policy checks, auditing, or interceptor pipelines — it is a low level executor @@ -36,10 +33,10 @@ internal sealed class MutationExecutor : IMutationExecutor /// Optional token to observe cancellation requests. /// The result of the mutation execution, including the new state and applied changes. /// - /// Thrown if the mutation execution exceeds the configured . + /// Thrown if the mutation execution is canceled via . /// /// - /// Thrown if the is signaled before or during execution. + /// Thrown if the configured execution timeout elapses before or during execution. /// public Task> ExecuteAsync( IMutation mutation, diff --git a/toc.yml b/toc.yml new file mode 100644 index 0000000..123148f --- /dev/null +++ b/toc.yml @@ -0,0 +1,28 @@ +- name: Home + href: README.md +- name: Packages + items: + - name: ModularityKit.Mutator + href: src/README.md + - name: ModularityKit.Mutator.Governance + href: src/Governance/README.md + - name: ModularityKit.Mutator.Governance.Redis + href: src/Redis/README.md +- name: Guides + items: + - name: Architecture + href: Docs/Architecture.md + - name: Core Concepts + href: Docs/Core-Concepts.md + - name: Execution Model + href: Docs/ExecutionModel.md + - name: Roadmap + href: Docs/Roadmap.md +- name: API + items: + - name: Reference + href: Docs/API/Reference.md + - name: Core API + href: Docs/API/API.md + - name: Redis API + href: Docs/API/Redis.md