Skip to content

Feat: Agreement Dispatcher#361

Merged
iancooper merged 29 commits into
masterfrom
feat/349-agreement-dispatcher
Jul 17, 2026
Merged

Feat: Agreement Dispatcher#361
iancooper merged 29 commits into
masterfrom
feat/349-agreement-dispatcher

Conversation

@iancooper

Copy link
Copy Markdown
Member

Provides an agreement dispatcher, based on Brighter, to route between a query and a handler based on query parameters and context

Closes #349

iancooper and others added 29 commits July 14, 2026 22:16
Adds the requirements and accepted ADR for spec 013-agreement_dispatcher,
which routes a query to a handler type based on the query instance and
IQueryContext (agreement dispatch), alongside existing type-based routing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add tasks.md sequencing the agreement-dispatcher implementation Tidy
First: a structural commit (IResolveHandlers seam, widened Get) before
the behavioural routing tasks, with per-behaviour /test-first tasks for
sync, async, stream, and DI. Record the passing adversarial tasks review
and update the spec status checklist.

Soften the requirements AC to permit mechanical call-site updates forced
by the ADR's deliberate Get-widen, while forbidding any change to test
behaviour or assertions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GpzgaSGjQVcoxdJnmHr3S7
Introduce IResolveHandlers role and FixedHandlerRoute, migrate all three
registry dictionaries from Dictionary<Type,Type> to
Dictionary<Type,IResolveHandlers>, widen Get to
Get(Type,IQuery,IQueryContext), and thread query+context through
PipelineBuilder's resolution helpers. FixedHandlerRoute ignores query and
context, so all existing behaviour and test assertions are unchanged.
Mechanical test call-site updates (Get(type) → Get(type, null, null)) are
the only test edits in this commit.

This is the structural seam required before agreement dispatch (spec 013).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…error handling (Phase 2)

RoutingException derives from Exception (not ConfigurationException) so routing failures
are distinguishable from "no handler registered" errors. The RoutingFailure enum exposes
two sub-cases — NoHandlerResolved and UnregisteredCandidate — via a Reason property, with
distinct composed messages per failure mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ment dispatch (Phase 3, task 1)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…3, task 2)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ull (Phase 3, task 3)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ns non-candidate type (Phase 3, task 4)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…stration time (Phase 3, task 5)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ped (Phase 3, task 6)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hase 3, task 7)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…sed Register (Phase 3, task 8)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nt-based routing (Phase 4, task 1)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Phase 4, task 2)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ed (Phase 4, task 3)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…steredCandidate (Phase 4, task 4)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… duplicate key (Phase 4, task 5)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ent-based routing (Phase 4b, task 1)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…(Phase 4b, task 2)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ved before enumeration (Phase 4b, task 3)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…isteredCandidate (Phase 4b, task 4)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d duplicate key (Phase 4b, task 5)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…o TryAdd all candidates (Phase 5, task 1)

Also fixes 9 pre-existing extension test failures caused by public handler types in ExportedDatedQuery.cs
being picked up by AddHandlersFromAssemblies and causing duplicate registration errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…k 2)

Override routing Register in ServiceCollectionHandlerRegistryAsync to TryAdd all candidate handler types, symmetric with the sync DI override.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…sk 3)

Override routing Register in ServiceCollectionStreamHandlerRegistry to TryAdd all candidate handler types, completing Phase 5 DI integration for all three registries (sync, async, stream).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full regression green (516 tests, net8 + net9). XML docs on all three
Get interfaces describe the three outcomes. Spec README and tasks.md
updated to reflect completed implementation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@iancooper iancooper self-assigned this Jul 16, 2026
@iancooper
iancooper requested a review from holytshirt as a code owner July 16, 2026 11:48
@iancooper iancooper added .NET Pull requests that update .net code 3 - Done V5 labels Jul 16, 2026
@iancooper
iancooper merged commit 3751654 into master Jul 17, 2026
4 checks passed
@iancooper
iancooper deleted the feat/349-agreement-dispatcher branch July 17, 2026 09:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3 - Done enhancement .NET Pull requests that update .net code V5

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create an Agreement Dispatcher based on the Query and Context

1 participant