refactor: iter2 minor — Normalizer/Polling/Idempotent via PatternKit (incl. dedup-on-failure bug fix)#26
Merged
Merged
Conversation
… execution
- Replace qwen3:30b-instruct with qwen2.5:1.5b (1.5B params, <=2B constraint)
everywhere the model is configured: OllamaAgentProvider default, OllamaFixture,
SemanticKernelE2ETests, AiDsl sample, TaskStream sample extension
- Reduce OllamaFixture warmup timeout from 300s to 120s; remove /no_think from
warmup prompt (qwen3-specific; harmless on qwen2.5 but unnecessary)
- Add xunit.runner.json to Tests.E2E with parallelizeTestCollections:false and
maxParallelThreads:1 – combined with the existing [Collection("Ollama")] attribute
this guarantees all Ollama-backed tests run one at a time
- Update OllamaFactAttribute skip message to reference new model
- Update OllamaOptionsTests default model assertion to match new default
- Update prerequisite XML doc comment in AgentLoopOllamaE2ETests
To run the Ollama-backed E2E tests locally:
ollama pull qwen2.5:1.5b
dotnet test tests/WorkflowFramework.Tests.E2E/WorkflowFramework.Tests.E2E.csproj \
--filter Category=E2E
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… seeded workflow
Adds the AI DSL Emitter demo to the dashboard in two complementary ways:
1. Template ("New from Template" browser): id=ai-dsl-emitter, name="AI DSL Emitter",
category="AI & Agents", marked IsFeatured=true with preview SVG.
2. Seeded workflow (open-existing list): id=sample-ai-dsl-emitter,
name="AI DSL Emitter", immediately visible in the workflow list on startup.
Step types used match the Extensions.AI implementation:
SelectProvider (Action) → EmitSteps (DslEmitterStep) → ApprovePlan (ApprovalStep)
→ BridgeContext (Action) → ExecuteEmittedSteps (WorkflowDslExecutorStep)
Also registers DslEmitterStep and WorkflowDslExecutorStep in StepTypeRegistry
so the designer UI can render their config schemas.
Tests: 43/43 passed (WorkflowTemplateLibraryTests + SampleWorkflowSeederTests).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…orkflow
The SelectProvider step in SampleWorkflowSeeder had the old expression
"Resolve the agent provider from {provider} (echo or ollama)..." with an
unresolved {provider} template variable. This made the seeded/open-existing
workflow appear broken in the dashboard.
Aligned the expression to match InMemoryWorkflowTemplateLibrary:
"Provider is configured as echo (offline/demo default). To run live,
change the provider field in EmitSteps to ollama before executing."
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Consumes the new primitives introduced in 0.113.0: - KeyedNormalizer<TKey,TRaw,TCanonical> - AsyncPollingConsumer<T>.PollOnceAsync - (IdempotentReceiver<TPayload,TResult> already in 0.112.0) Adds NuGet.Config to resolve 0.113.0 from the local-packages feed until the release is published to nuget.org. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…NormalizerStep Replace bespoke dictionary dispatch with KeyedNormalizer<string,IWorkflowContext,IWorkflowContext>. The KeyedNormalizer provides O(1) keyed dispatch identical in semantics to the prior dictionary lookup. The original InvalidOperationException contract is preserved by wrapping KeyNotFoundException from the PatternKit miss path, keeping the test UnknownFormatNoDefaultThrows stable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
….PollOnceAsync in PollingConsumerStep Replace bespoke single-shot poll with AsyncPollingConsumer<IReadOnlyList<T>>.PollOnceAsync. The IPollingSource<T> is bridged via the WithSource delegate; PollOnceAsync handles one poll cycle without entering the continuous run loop. The ResultKey write contract and IReadOnlyList<T> output type are preserved. Public step API is unchanged. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BEHAVIOR CHANGE: Previously, a step failure permanently locked the idempotency key, preventing retries. This was a latent bug — failure should not lock future attempts. PatternKit's claim/complete/fail semantics correctly allow retry after failure. IdempotentReceiverStep now uses IIdempotencyStore (PatternKit interface) with claim → invoke → MarkCompleted/MarkFailed semantics. The default store (RetryAfterFailureIdempotencyStore) resets a Failed key to Processing on the next TryClaim, allowing retry. A Completed key is still suppressed, preserving the successful-dedup contract. Test `ReAttemptAfterExceptionIsSkipped` renamed to `ReAttemptAfterExceptionIsAllowed` with assertion flipped. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…o Adopted Records the Iteration 2 Phase 2 adoptions: - NormalizerStep → KeyedNormalizer<string,IWorkflowContext,IWorkflowContext> - PollingConsumerStep → AsyncPollingConsumer<T>.PollOnceAsync - IdempotentReceiverStep → IIdempotencyStore (with IdempotentReceiverStep bug fix noted) Updates Future Evaluation Targets to reflect remaining deferred items (Phase 3). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…otstrap The 0.113.0 release is not yet published to nuget.org (it ships from the feat/keyed-normalizer-poll-once-outbox-ext branch). To unblock CI, bundle the pre-built .nupkg in eng/local-feed/ and point NuGet.Config at it via a relative path. Remove eng/local-feed/ and NuGet.Config once the upstream PatternKit release is published. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #26 +/- ##
==========================================
+ Coverage 89.78% 89.81% +0.02%
==========================================
Files 291 291
Lines 8282 8342 +60
Branches 1496 1502 +6
==========================================
+ Hits 7436 7492 +56
- Misses 522 524 +2
- Partials 324 326 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…storePackagesWithLockFile=false The --force-evaluate restore generated packages.lock.json files for Approvals.Acceptance and Approvals.Integration.Tests, which have RestorePackagesWithLockFile=false. Committing them caused NU1005 on the CodeQL workflow. Remove from index and add to .gitignore. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PatternKit.Core 0.113.0 is now published to NuGet.org. The local nupkg + NuGet.Config workaround introduced earlier in this branch is no longer needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n NuGet.org The local nupkg bundled in eng/local-feed had a different content hash than the package published to NuGet.org. Update all 91 packages.lock.json files so NU1403 hash validation passes against the official feed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Code Coverage |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
KeyedNormalizer<string,IWorkflowContext,IWorkflowContext>(PatternKit 0.113.0): Bespoke dict-key dispatch replaced; originalInvalidOperationExceptioncontract preserved by wrappingKeyNotFoundException.AsyncPollingConsumer<T>.PollOnceAsync(PatternKit 0.113.0): Single-shot poll wired viaWithSourcebridge;ResultKey/IReadOnlyList<T>output contract unchanged.IIdempotencyStoreclaim/complete/fail semantics (PatternKit 0.112.0+): Bug fix — prior bespokeHashSet.Add-before-invokepermanently locked idempotency keys on failure. New behavior:Completed= deduplicated;Failed= retry allowed.Per-step delta
KeyedNormalizer<string,IWorkflowContext,IWorkflowContext>AsyncPollingConsumer<T>.PollOnceAsyncIIdempotencyStore(TryClaimAsync/MarkCompletedAsync/MarkFailedAsync)Test changes
Only IdempotentReceiverStep required a test update (the intended behavioral fix):
ReAttemptAfterExceptionIsSkipped→ renamedReAttemptAfterExceptionIsAllowed1→2(retry is now allowed after failure).plan/patternkit-iteration-2.md §4)Infrastructure note
PatternKit 0.113.0 is resolved from the
local-packagesfeed (C:\git\local-packages) via the project-levelNuGet.Config. The package was built frompatternkit-iter2(thefeat/keyed-normalizer-poll-once-outbox-extbranch). Once the upstream PatternKit PR is merged and 0.113.0 published to nuget.org, theNuGet.Configcan be removed in a follow-up chore commit.RELEASE NOTE
🤖 Generated with Claude Code