diff --git a/Directory.Build.props b/Directory.Build.props
index 9e072ba..97917cc 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -56,7 +56,7 @@
- $(NoWarn);CA1014;CA1724;CA1812;IDE0290;IL2026;IL2067;IL2070;IL2075;IL3050;IL2104;IL3053
+ $(NoWarn);CA1014;CA1724;CA1812;IDE0290
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 9aed975..c3e4c8b 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -5,15 +5,19 @@
true
-
+
+
+
+
+
-
+
diff --git a/kanban/in-progress/001-address-code-review-blockers-for-v100-release.md b/kanban/in-progress/001-address-code-review-blockers-for-v100-release.md
index 1a60da4..6052949 100644
--- a/kanban/in-progress/001-address-code-review-blockers-for-v100-release.md
+++ b/kanban/in-progress/001-address-code-review-blockers-for-v100-release.md
@@ -16,8 +16,10 @@ Code review report: `.agent/workspace/2026-02-23T00-00-00_code-review-release-re
- Add `ToolsDirectory` for future tooling support
- Note: TestsDirectory, SamplesDirectory, BenchmarksDirectory left in place for future use
-- [ ] **Add automated tests**
- - Create test project (suggested: `tests/TimeWarp.Builder.Tests/`)
+- [x] **Add automated tests** (2026-07-02)
+ - Implemented as TimeWarp.Jaribu runfiles under `tests/` (repo convention) rather than a dotnet-test project; `dev test` runs each runfile and aggregates exit codes
+ - 21 tests across 6 files: 4 scope-extension files + 2 interface integration files (concrete builders modeled on TimeWarp.Nuru's usage), covering null guards and covariance
+ - Original scope:
- Test all 4 scope extension methods:
- `Also` - executes action, returns original object
- `Apply` - executes action, returns original object
@@ -37,7 +39,7 @@ Code review report: `.agent/workspace/2026-02-23T00-00-00_code-review-release-re
### ⚠️ High Priority (strongly recommended)
-- [ ] **Improve README.md**
+- [x] **Improve README.md** (2026-07-02)
- Add installation section with `dotnet add package TimeWarp.Builder`
- Add requirements section (target framework: .NET 10.0)
- Add license badge and link to LICENSE file
@@ -45,7 +47,8 @@ Code review report: `.agent/workspace/2026-02-23T00-00-00_code-review-release-re
- Add design rationale explaining `Also` vs `Apply` distinction
- Link to GitHub repository
-- [ ] **Wire up package icon**
+- [x] **Wire up package icon** — resolved with `logo.png` in `source/Directory.Build.props`; ganda's nuget-package-icon audit check passes
+ - Original suggestion:
- Add `timewarp-builder-avatar.png` (convert SVG to PNG if needed, NuGet prefers PNG)
- Add icon file reference to `.csproj`:
```xml
@@ -55,7 +58,7 @@ Code review report: `.agent/workspace/2026-02-23T00-00-00_code-review-release-re
```
- Note: `assets/timewarp-builder-avatar.svg` exists but SVG icons in NuGet packages have limited client support
-- [ ] **Prune `Directory.Packages.props`**
+- [x] **Prune `Directory.Packages.props`** (2026-07-02, ganda audit CPM cleanup; Jaribu/Shouldly re-added for tests)
- Remove unused package groups:
- Serilog (Logging - Serilog section)
- OpenTelemetry
@@ -67,14 +70,15 @@ Code review report: `.agent/workspace/2026-02-23T00-00-00_code-review-release-re
- Keep only packages actually referenced by this library (likely just analyzers and Microsoft.Extensions if needed)
- Note: `TimeWarp.Builder` self-reference can also be removed
-- [ ] **Review AOT warning suppressions**
+- [x] **Review AOT warning suppressions** (2026-07-02) — removed all seven IL* suppressions; both the library build and the dev-cli AOT publish verified clean without them
+ - Original scope:
- Current global suppressions in `Directory.Build.props`: `IL2026;IL2067;IL2070;IL2075;IL3050;IL2104;IL3053`
- Evaluate if these are truly needed for this library (it has no reflection/dynamic code)
- If they are false positives, consider removing the global suppression and testing AOT build
### Nice to Have (low priority)
-- [ ] Add `#region Purpose` / `#region Design` context blocks to source files per csharp skill conventions
+- [x] Add `#region Purpose` / `#region Design` context blocks to source files per csharp skill conventions (2026-07-02)
- [ ] Add `CHANGELOG.md` for v1.0.0 release notes
- [ ] Consider `IBuildAsync` interface for async build scenarios (future v1.x)
diff --git a/readme.md b/readme.md
index e87d454..0e453a7 100644
--- a/readme.md
+++ b/readme.md
@@ -1,12 +1,28 @@
# TimeWarp.Builder
+[](https://www.nuget.org/packages/TimeWarp.Builder)
+[](https://www.nuget.org/packages/TimeWarp.Builder)
+[](https://github.com/TimeWarpEngineering/timewarp-builder/actions/workflows/workflow.yml)
+[](LICENSE)
+
Fluent builder interfaces and Kotlin-inspired scope extensions for .NET.
+## Installation
+
+```bash
+dotnet add package TimeWarp.Builder --prerelease
+```
+
+## Requirements
+
+- .NET 10.0 or later
+- Fully AOT- and trim-compatible (no reflection, no dynamic code)
+
## Interfaces
### IBuilder\
-Interface for standalone builders that create objects via `Build()`.
+Interface for standalone builders that create objects via `Build()`. `TBuilt` is covariant, so an `IBuilder` can be used wherever an `IBuilder` is expected.
```csharp
public class MyWidgetBuilder : IBuilder
@@ -23,7 +39,7 @@ Widget widget = new MyWidgetBuilder()
### INestedBuilder\
-Interface for nested builders that return to a parent context via `Done()`.
+Interface for nested builders that return to a parent context via `Done()`. `Done()` performs three things: builds the child, hands the result to the parent, and returns the parent for continued chaining.
```csharp
// Nested builder returns to parent after building
@@ -36,21 +52,38 @@ app.Map(route => route
## Scope Extensions
-Kotlin-inspired extension methods for fluent object manipulation.
+Kotlin-inspired extension methods for fluent object manipulation. Because they attach to every type (unconstrained `T`), any object can participate in a fluent chain without its type opting in.
+
+| Method | Returns | Use for |
+|--------|---------|---------|
+| `Also` | The original object | Side effects mid-chain (logging, diagnostics) |
+| `Apply` | The original object | Configuring the object mid-chain |
+| `Let` | The transform result | Converting to a different type/value |
+| `Run` | Nothing (`void`) | Terminal action at the end of a chain |
+
+### Also vs Apply
+
+`Also` and `Apply` are mechanically identical — both execute an action and return the original object. They exist separately to signal *intent* at the call site, mirroring Kotlin's `also`/`apply` distinction: use `Apply` when the action configures the object itself, and `Also` when the action is an incidental side effect like logging.
+
+```csharp
+app.Map("status", handler)
+ .Apply(r => r.AsQuery()) // configures the route
+ .Also(r => logger.LogDebug("mapped {r}", r)); // side effect, not configuration
+```
### Also
-Executes an action on the object and returns the original object. Useful for side effects during method chaining.
+Executes an action on the object and returns the original object.
```csharp
var builder = new AppBuilder()
- .Also(b => Console.WriteLine("Building app..."))
+ .Also(b => logger.LogDebug("Building app..."))
.Configure(options);
```
### Apply
-Configures the object and returns the original object. Semantically similar to `Also` but with clearer intent for configuration.
+Configures the object and returns the original object.
```csharp
app.Map("status", handler)
@@ -72,3 +105,22 @@ Executes an action on the object with no return value. Terminal operation in a m
```csharp
app.Build().Run(a => a.RunAsync(args));
```
+
+All four methods throw `ArgumentNullException` when the delegate is null.
+
+## Used By
+
+- [TimeWarp.Nuru](https://github.com/TimeWarpEngineering/timewarp-nuru) — route, endpoint, group, and key-binding builders implement `IBuilder` / `INestedBuilder`
+- [TimeWarp.Terminal](https://github.com/TimeWarpEngineering/timewarp-terminal)
+
+## Testing
+
+Tests are [TimeWarp.Jaribu](https://github.com/TimeWarpEngineering/timewarp-jaribu) runfiles under `tests/`. Run them all with `dev test`, or any file directly:
+
+```bash
+dotnet run tests/scope-extensions.also.cs
+```
+
+## Unlicense
+
+This is free and unencumbered software released into the public domain — see [LICENSE](LICENSE).
diff --git a/source/Directory.Build.props b/source/Directory.Build.props
index 35cb2bd..dcf5e81 100644
--- a/source/Directory.Build.props
+++ b/source/Directory.Build.props
@@ -4,7 +4,7 @@
- 1.0.0-beta.3
+ 1.0.0Steven T. Cramerhttps://github.com/TimeWarpEngineering/timewarp-builderUnlicense
diff --git a/source/timewarp-builder/global-usings.cs b/source/timewarp-builder/global-usings.cs
index 871318d..ac3de30 100644
--- a/source/timewarp-builder/global-usings.cs
+++ b/source/timewarp-builder/global-usings.cs
@@ -1 +1,5 @@
+#region Purpose
+// Global using directives for the TimeWarp.Builder library.
+#endregion
+
global using System;
diff --git a/source/timewarp-builder/i-builder.cs b/source/timewarp-builder/i-builder.cs
index 0d05760..bb55cb3 100644
--- a/source/timewarp-builder/i-builder.cs
+++ b/source/timewarp-builder/i-builder.cs
@@ -1,3 +1,13 @@
+#region Purpose
+// Contract for standalone builders that produce their configured object via Build().
+#endregion
+
+#region Design
+// TBuilt is covariant (out) so an IBuilder is usable where an IBuilder is
+// expected. Builders that finish by returning to a parent context instead implement
+// INestedBuilder; the two interfaces are intentionally minimal and independent.
+#endregion
+
namespace TimeWarp.Builder;
///
diff --git a/source/timewarp-builder/i-nested-builder.cs b/source/timewarp-builder/i-nested-builder.cs
index ae3d160..162ff4b 100644
--- a/source/timewarp-builder/i-nested-builder.cs
+++ b/source/timewarp-builder/i-nested-builder.cs
@@ -1,3 +1,14 @@
+#region Purpose
+// Contract for nested builders that finish via Done() and return control to a parent builder.
+#endregion
+
+#region Design
+// Done() bundles three steps: build the child, hand the result to the parent, return the
+// parent — enabling deep fluent chains without the caller juggling intermediate results.
+// TParent is covariant (out) and constrained to class; nested builders typically wrap a
+// standalone IBuilder internally (see TimeWarp.Nuru's NestedCompiledRouteBuilder).
+#endregion
+
namespace TimeWarp.Builder;
///
diff --git a/source/timewarp-builder/scope-extensions.cs b/source/timewarp-builder/scope-extensions.cs
index 7f4d844..5ded074 100644
--- a/source/timewarp-builder/scope-extensions.cs
+++ b/source/timewarp-builder/scope-extensions.cs
@@ -1,3 +1,15 @@
+#region Purpose
+// Kotlin-inspired scope extension methods (Also, Apply, Let, Run) for fluent object manipulation.
+#endregion
+
+#region Design
+// Also and Apply share an implementation; they exist separately to signal intent at the call
+// site (Apply = configuration, Also = incidental side effect), mirroring Kotlin's apply/also.
+// T is deliberately unconstrained so the extensions attach to every type — any object can join
+// a fluent chain without its type opting in; the IntelliSense noise is the accepted trade-off.
+// Delegates are null-guarded; the receiver is not, matching BCL extension-method convention.
+#endregion
+
namespace TimeWarp.Builder;
///
diff --git a/tests/.gitkeep b/tests/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
new file mode 100644
index 0000000..42ddb3b
--- /dev/null
+++ b/tests/Directory.Build.props
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(NoWarn);CA1707;CA1515;CA1812;CA1859;CA1861;CA2007;CS1591;IDE0058;IDE0210;IDE0211;RCS1046
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/i-builder.build.cs b/tests/i-builder.build.cs
new file mode 100755
index 0000000..e49d54c
--- /dev/null
+++ b/tests/i-builder.build.cs
@@ -0,0 +1,74 @@
+#!/usr/bin/env -S dotnet --
+
+#region Purpose
+// Tests for IBuilder: standalone builders produce their configured object via Build().
+#endregion
+
+#if !JARIBU_MULTI
+return await RunAllTests();
+#endif
+
+namespace IBuilder_
+{
+ [TestTag("Interfaces")]
+ public sealed class Build_Given_
+ {
+ [ModuleInitializer]
+ internal static void Register() => RegisterTests();
+
+ public static async Task ConcreteBuilder_Should_ReturnConfiguredObject()
+ {
+ Widget widget = new WidgetBuilder()
+ .WithName("gizmo")
+ .WithSize(10)
+ .Build();
+
+ widget.Name.ShouldBe("gizmo");
+ widget.Size.ShouldBe(10);
+ await Task.CompletedTask;
+ }
+
+ public static async Task CovariantTBuilt_Should_AssignToBaseTypedInterface()
+ {
+ // IBuilder covariance: a Widget builder is usable where an object builder is expected
+ IBuilder