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
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -473,11 +473,11 @@ var cachedRemoteProxy = Proxy<int, string>.Create(id => remoteProxy.Execute(id))
---

## Patterns Table
PatternKit currently tracks 107 production-readiness patterns. Each catalog pattern is represented in tests, documentation, real-world examples, IoC integration, and the BenchmarkDotNet coverage matrix.
PatternKit currently tracks 108 production-readiness patterns. Each catalog pattern is represented in tests, documentation, real-world examples, IoC integration, and the BenchmarkDotNet coverage matrix.

| Category | Count | Patterns |
| --- | ---: | --- |
| Application Architecture | 22 | Activity Tracker, Aggregate Root, Anti-Corruption Layer, Audit Log, Bounded Context, Context Map, CQRS, Data Mapper, Domain Event, Domain Service, Event Sourcing, Feature Toggle, Identity Map, Materialized View, Repository, Service Layer, Specification, Table Data Gateway, Timeout Manager, Transaction Script, Unit of Work, Value Object |
| Application Architecture | 23 | Activity Tracker, Aggregate Root, Anti-Corruption Layer, Audit Log, Bounded Context, Context Map, CQRS, Data Mapper, Domain Event, Domain Service, Event Sourcing, Feature Toggle, Identity Map, Manual Task Gate, Materialized View, Repository, Service Layer, Specification, Table Data Gateway, Timeout Manager, Transaction Script, Unit of Work, Value Object |
| Behavioral | 11 | Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor |
| Cloud Architecture | 17 | Ambassador, Backends for Frontends, Bulkhead, Cache-Aside, Circuit Breaker, External Configuration Store, Gateway Aggregation, Gateway Routing, Health Endpoint Monitoring, Leader Election, Priority Queue, Queue-Based Load Leveling, Rate Limiting, Retry, Scheduler Agent Supervisor, Sidecar, Strangler Fig |
| Creational | 5 | Abstract Factory, Builder, Factory Method, Prototype, Singleton |
Expand All @@ -497,6 +497,8 @@ BenchmarkDotNet guidance is documented in [docs/guides/benchmarks.md](docs/guide
| Adapter | Execution | 59.084 ns | 416 B | 20.479 ns | 80 B | Generated adapter execution was faster and allocated less for shipment adaptation. |
| Activity Tracker | Construction | 13.09 ns | 152 B | 12.98 ns | 152 B | Same allocation; generated was slightly faster in this microbenchmark. |
| Activity Tracker | Execution | 446.88 ns | 1,656 B | 452.36 ns | 1,656 B | Same allocation; fluent was slightly faster for dashboard loading gates. |
| Manual Task Gate | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Manual Task Gate | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Timeout Manager | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Timeout Manager | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Aggregate Root | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using BenchmarkDotNet.Attributes;
using PatternKit.Application.ManualTaskGates;
using PatternKit.Examples.ManualTaskGateDemo;

namespace PatternKit.Benchmarks.Application;

[BenchmarkCategory("ApplicationArchitecture", "ManualTaskGate")]
public class ManualTaskGateBenchmarks
{
private static readonly OrderApprovalRequest Request = new(
Guid.Parse("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"),
"REQ-200",
1250.00m,
"checkout-api");

[Benchmark(Baseline = true, Description = "Fluent: create manual task gate")]
[BenchmarkCategory("Fluent", "Construction")]
public ManualTaskGate<Guid> Fluent_CreateManualTaskGate()
=> OrderApprovalManualTaskGates.CreateFluent();

[Benchmark(Description = "Generated: create manual task gate")]
[BenchmarkCategory("Generated", "Construction")]
public ManualTaskGate<Guid> Generated_CreateManualTaskGate()
=> GeneratedOrderApprovalManualTaskGate.CreateGenerated();

[Benchmark(Description = "Fluent: approve order manual task")]
[BenchmarkCategory("Fluent", "Execution")]
public OrderApprovalSummary Fluent_ApproveOrder()
=> OrderApprovalManualTaskGateDemoRunner.RunFluent(Request);

[Benchmark(Description = "Generated: approve order manual task")]
[BenchmarkCategory("Generated", "Execution")]
public OrderApprovalSummary Generated_ApproveOrder()
=> OrderApprovalManualTaskGateDemoRunner.RunGeneratedStatic(Request);
}
23 changes: 23 additions & 0 deletions docs/examples/order-approval-manual-task-gate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Order Approval Manual Task Gate

This example shows a high-value checkout flow that pauses on manual approval before fulfillment can continue.

```csharp
var request = new OrderApprovalRequest(orderId, "REQ-200", 1250.00m, "checkout-api");
var summary = OrderApprovalManualTaskGateDemoRunner.RunFluent(request);
```

The source-generated route uses the same workflow through a generated factory:

```csharp
var gate = GeneratedOrderApprovalManualTaskGate.CreateGenerated();
var service = new OrderApprovalManualTaskService(gate);
```

Import the demo into an existing host with:

```csharp
services.AddOrderApprovalManualTaskGateDemo();
```

The registration provides `ManualTaskGate<Guid>`, `OrderApprovalManualTaskService`, and `OrderApprovalManualTaskGateDemoRunner`.
3 changes: 3 additions & 0 deletions docs/examples/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
- name: Dashboard Activity Tracker
href: dashboard-activity-tracker.md

- name: Order Approval Manual Task Gate
href: order-approval-manual-task-gate.md

- name: Order Reservation Timeout Manager
href: order-reservation-timeout-manager.md

Expand Down
1 change: 1 addition & 0 deletions docs/generators/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ PatternKit includes a Roslyn incremental generator package (`PatternKit.Generato
| [**Repository**](repository.md) | In-memory repository factories from key selectors | `[GenerateRepository]` |
| [**Anti-Corruption Layer**](anti-corruption-layer.md) | External-to-domain translation boundaries with validation | `[GenerateAntiCorruptionLayer]` |
| [**Activity Tracker**](activity-tracker.md) | Active-work tracker gates for loading and readiness workflows | `[GenerateActivityTracker]` |
| [**Manual Task Gate**](manual-task-gate.md) | Human approval gates for workflow pauses and manual decisions | `[GenerateManualTaskGate]` |
| [**Timeout Manager**](timeout-manager.md) | Deadline registry for expiring pending workflow work | `[GenerateTimeoutManager]` |
| [**Audit Log**](audit-log.md) | Append-only audit log factories from key selectors | `[GenerateAuditLog]` |
| [**Unit of Work**](unit-of-work.md) | Ordered commit and rollback units | `[GenerateUnitOfWork]` |
Expand Down
18 changes: 18 additions & 0 deletions docs/generators/manual-task-gate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Manual Task Gate Generator

The Manual Task Gate generator creates a strongly typed factory for `ManualTaskGate<TKey>` from a partial host type.

```csharp
using PatternKit.Generators.ManualTaskGates;

[GenerateManualTaskGate(typeof(Guid), FactoryMethodName = "CreateGenerated", GateName = "order-approval-gate")]
public static partial class GeneratedOrderApprovalManualTaskGate;
```

Generated usage:

```csharp
ManualTaskGate<Guid> gate = GeneratedOrderApprovalManualTaskGate.CreateGenerated();
```

The host type must be partial. `FactoryMethodName` and `GateName` must be non-empty when provided.
3 changes: 3 additions & 0 deletions docs/generators/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@
- name: Materialized View
href: materialized-view.md

- name: Manual Task Gate
href: manual-task-gate.md

- name: Iterator
href: iterator.md

Expand Down
10 changes: 7 additions & 3 deletions docs/guides/benchmark-results.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ The latest measured timings below were captured on Windows 11, Intel Core i9-149
| Adapter | Execution | 59.084 ns | 416 B | 20.479 ns | 80 B | Generated adapter execution was faster and allocated less for shipment adaptation. |
| Activity Tracker | Construction | 13.09 ns | 152 B | 12.98 ns | 152 B | Same allocation; generated was slightly faster in this microbenchmark. |
| Activity Tracker | Execution | 446.88 ns | 1,656 B | 452.36 ns | 1,656 B | Same allocation; fluent was slightly faster for dashboard loading gates. |
| Manual Task Gate | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Manual Task Gate | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Timeout Manager | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Timeout Manager | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Aggregate Root | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
Expand Down Expand Up @@ -232,19 +234,19 @@ The latest measured timings below were captured on Windows 11, Intel Core i9-149

## Coverage Matrix Summary

The coverage matrix currently publishes 107 catalog patterns and 428 pattern route results. Each pattern has four BenchmarkDotNet routes: fluent construction, fluent execution, source-generated construction, and source-generated execution. The reusable hosting integration matrix publishes 9 reusable hosting integration route results for package-level `IServiceCollection` registrations.
The coverage matrix currently publishes 108 catalog patterns and 432 pattern route results. Each pattern has four BenchmarkDotNet routes: fluent construction, fluent execution, source-generated construction, and source-generated execution. The reusable hosting integration matrix publishes 9 reusable hosting integration route results for package-level `IServiceCollection` registrations.

| Category | Patterns | Published route results |
| --- | ---: | ---: |
| Application Architecture | 22 | 88 |
| Application Architecture | 23 | 92 |
| Behavioral | 11 | 44 |
| Cloud Architecture | 17 | 68 |
| Creational | 5 | 20 |
| Enterprise Integration | 41 | 164 |
| Messaging Reliability | 3 | 12 |
| Structural | 7 | 28 |

The generator matrix currently publishes 102 generator source route results.
The generator matrix currently publishes 103 generator source route results.

## Hosting Integration Matrix Results

Expand All @@ -265,6 +267,7 @@ The generator matrix currently publishes 102 generator source route results.
| Category | Pattern | Fluent construction | Fluent execution | Generated construction | Generated execution |
| --- | --- | --- | --- | --- | --- |
| Application Architecture | Activity Tracker | Covered | Covered | Covered | Covered |
| Application Architecture | Manual Task Gate | Covered | Covered | Covered | Covered |
| Application Architecture | Timeout Manager | Covered | Covered | Covered | Covered |
| Application Architecture | Aggregate Root | Covered | Covered | Covered | Covered |
| Application Architecture | Anti-Corruption Layer | Covered | Covered | Covered | Covered |
Expand Down Expand Up @@ -377,6 +380,7 @@ The generator matrix currently publishes 102 generator source route results.
| --- | --- | --- |
| ActivityTrackerGenerator | `src/PatternKit.Generators/ActivityTracking/ActivityTrackerGenerator.cs` | Covered |
| TimeoutManagerGenerator | `src/PatternKit.Generators/Timeouts/TimeoutManagerGenerator.cs` | Covered |
| ManualTaskGateGenerator | `src/PatternKit.Generators/ManualTaskGates/ManualTaskGateGenerator.cs` | Covered |
| AggregateCommandHandlerGenerator | `src/PatternKit.Generators/Aggregates/AggregateCommandHandlerGenerator.cs` | Covered |
| AdapterGenerator | `src/PatternKit.Generators/Adapter/AdapterGenerator.cs` | Covered |
| AmbassadorGenerator | `src/PatternKit.Generators/Ambassador/AmbassadorGenerator.cs` | Covered |
Expand Down
2 changes: 2 additions & 0 deletions docs/guides/benchmarks.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ The following numbers were captured on Windows 11, Intel Core i9-14900K, .NET SD
| Adapter | Execution | 59.084 ns | 416 B | 20.479 ns | 80 B | Generated adapter execution was faster and allocated less for shipment adaptation. |
| Activity Tracker | Construction | 13.09 ns | 152 B | 12.98 ns | 152 B | Same allocation; generated was slightly faster in this microbenchmark. |
| Activity Tracker | Execution | 446.88 ns | 1,656 B | 452.36 ns | 1,656 B | Same allocation; fluent was slightly faster for dashboard loading gates. |
| Manual Task Gate | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Manual Task Gate | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Timeout Manager | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Timeout Manager | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Aggregate Root | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
Expand Down
1 change: 1 addition & 0 deletions docs/guides/pattern-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ The source of truth is `PatternKitPatternCatalog` in `src/PatternKit.Examples/Pr
| Application Architecture | Materialized View | `IMaterializedView<TState,TEvent>` and `MaterializedView<TState,TEvent>` | Materialized View generator |
| Application Architecture | Anti-Corruption Layer | `AntiCorruptionLayer<TExternal, TDomain>` | Anti-Corruption Layer generator |
| Application Architecture | Activity Tracker | `ActivityTracker` | Activity Tracker generator |
| Application Architecture | Manual Task Gate | `ManualTaskGate<TKey>` | Manual Task Gate generator |
| Application Architecture | Timeout Manager | `TimeoutManager<TKey>` | Timeout Manager generator |

## Research Baselines
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ if (parser.Execute("123", out var value))

## 📚 Available Patterns

PatternKit covers 107 production-readiness patterns with fluent APIs, source-generated routes where applicable, IoC integration examples, TinyBDD coverage, and BenchmarkDotNet coverage-matrix validation:
PatternKit covers 108 production-readiness patterns with fluent APIs, source-generated routes where applicable, IoC integration examples, TinyBDD coverage, and BenchmarkDotNet coverage-matrix validation:

| Category | Count | Patterns |
| --- | ---: | --- |
| Application Architecture | 22 | Activity Tracker, Aggregate Root, Anti-Corruption Layer, Audit Log, Bounded Context, Context Map, CQRS, Data Mapper, Domain Event, Domain Service, Event Sourcing, Feature Toggle, Identity Map, Materialized View, Repository, Service Layer, Specification, Table Data Gateway, Timeout Manager, Transaction Script, Unit of Work, Value Object |
| Application Architecture | 23 | Activity Tracker, Aggregate Root, Anti-Corruption Layer, Audit Log, Bounded Context, Context Map, CQRS, Data Mapper, Domain Event, Domain Service, Event Sourcing, Feature Toggle, Identity Map, Manual Task Gate, Materialized View, Repository, Service Layer, Specification, Table Data Gateway, Timeout Manager, Transaction Script, Unit of Work, Value Object |
| Behavioral | 11 | Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor |
| Cloud Architecture | 17 | Ambassador, Backends for Frontends, Bulkhead, Cache-Aside, Circuit Breaker, External Configuration Store, Gateway Aggregation, Gateway Routing, Health Endpoint Monitoring, Leader Election, Priority Queue, Queue-Based Load Leveling, Rate Limiting, Retry, Scheduler Agent Supervisor, Sidecar, Strangler Fig |
| Creational | 5 | Abstract Factory, Builder, Factory Method, Prototype, Singleton |
Expand Down
26 changes: 26 additions & 0 deletions docs/patterns/application/manual-task-gate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Human Approval / Manual Task Gate

Manual Task Gate tracks human-owned work that blocks a workflow until a person approves, rejects, cancels, or completes the task. Use it for high-value order reviews, exception handling, finance approvals, manual fraud checks, and operations where automated orchestration must pause on an explicit decision.

`ManualTaskGate<TKey>` provides the fluent runtime path:

```csharp
var gate = ManualTaskGate<Guid>
.Create("order-approval-gate")
.Build();

gate.Open(orderId, "Approve high value order", "order-approvals", requestId);
var decision = gate.Approve(orderId, "case-manager", "Approved for fulfillment.");
var state = gate.GetGateState();
```

The gate remains blocked while any task has `ManualTaskStatus.Pending`. Decisions are retained in the snapshot so operators can inspect which tasks were approved, rejected, or canceled.

Use the source-generated path when you want a reusable named gate factory:

```csharp
[GenerateManualTaskGate(typeof(Guid), FactoryMethodName = "CreateGenerated", GateName = "order-approval-gate")]
public static partial class GeneratedOrderApprovalManualTaskGate;
```

The generated factory returns the same `ManualTaskGate<Guid>` fluent object without handwritten boilerplate.
2 changes: 2 additions & 0 deletions docs/patterns/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,8 @@
href: application/context-map.md
- name: Table Data Gateway
href: application/table-data-gateway.md
- name: Manual Task Gate
href: application/manual-task-gate.md
- name: Timeout Manager
href: application/timeout-manager.md
- name: Event Sourcing
Expand Down
Loading
Loading