Extends WorkflowCanonicalArtifactGenerator (ships alongside the existing
analyzer in the same Roslyn component) to walk the real-world builder
surface used by the Bulstrad corpus.
New step visitors (inside StartWith(flow => ...) lambdas and
OnComplete(flow => ...) lambdas):
* Set(key, expr) and SetIfHasValue(key, expr) -> set-state
* ActivateTask(name) -> activate-task
* Complete() -> complete
* WhenExpression(name, cond, whenTrue, whenElse?) -> decision with
nested whenTrue/whenElse step sequences (lambdas walked recursively)
* Call(stepName, address, payload?, resultKey?, whenFailure?,
whenTimeout?, timeoutSeconds?) -> call-transport
Address resolution covers:
* new LegacyRabbitAddress("cmd") and new LegacyRabbitAddress("cmd", mode)
* new Address("serviceName", "command")
* Referenced static readonly fields -- walks the field's declarator
initializer and emits the address there (matches real Bulstrad pattern
"private static readonly LegacyRabbitAddress FooAddress = new(...)").
AddTask chains:
WorkflowHumanTask.For<T>("name", "type", "route")
.WithRoles(...) / .WithTimeout(...) / .WithRoute(expr)
/ .WithPayload(expr) / .OnComplete(flow => ...)
The generator walks each segment and appends a CanonicalTask to
definition.tasks[].
IR extended:
* CanonicalSteps.cs -- SetStateStep, ActivateTaskStep, CompleteStep,
DecisionStep, TransportCallStep, AssignBusinessReferenceStep,
StepSequence
* CanonicalAddress.cs -- MicroserviceAddress, LegacyRabbitAddress
* CanonicalTask.cs -- CanonicalTask
* CanonicalDefinition now emits the full top-level shape
(workflowRoles[], start{initializeStateExpression, initialTaskName,
initialSequence}, tasks[], requiredModules[], requiredCapabilities[]).
Tests: 36/36 pass (31 existing + 5 new covering the step/task surface,
including a WF020 fallback test for the not-yet-supported Fork().
Still not supported (WF020 continues to fire): Fork, Repeat, Wait,
WaitForSignal, ContinueWith, SubWorkflow, SetBusinessReference with
object-initialiser syntax, QueryGraphql, HttpAddress / GraphqlAddress.
Follow-up commits extend these as the corpus migration surfaces them.