v1.40.0 ✅

  • ReasonMetadata — new sealed record capturing CallerMember, CallerFile, CallerLine via compiler-injected [CallerMemberName/FilePath/LineNumber] on factory methods; zero-allocation Empty singleton; completely separate from Tags (no framework leakage into user metadata)
  • IReasonMetadata — secondary capability interface (same pattern as IAsyncDisposable); opt-in metadata exposure from IReason-typed references without breaking existing implementations; Reason base class implements it automatically
  • ReasonMetadataExtensionsTryGetMetadata(IReason) and HasCallerInfo(IReason) helpers; null-safe via pattern matching
  • Static error factoriesValidationError.Field(field, msg), ForbiddenError.For(action, resource), ConflictError.Duplicate(entity, field, value), ConflictError.Duplicate<T>(field, value); each captures CallerMember at the factory call site; old multi-arg constructors marked [Obsolete]

- RESL1010 — new analyzer: warns when a Result<T> local variable has no failure-aware usage in the enclosing block and is not returned (errors silently swallowed)

- RESL2002 — new analyzer: warns when ErrorsOf.Match() provides fewer handlers than the union has type arguments (non-exhaustive match)

- RESL1021 — new analyzer: warns when an IError/IReason implementation has a public constructor with 2+ required parameters; (), (string), (string, Exception), and [Obsolete]-marked ctors exempt

  • ResultFlow ErrorHint — Mermaid failure edges now annotate the error type for body-scan pipelines: .Ensure(pred, new NotFoundError(...))|"fail: NotFoundError"|; syntactic extraction (no semantic model required); ErrorType from type-read mode still takes precedence
  • 158 features, >4,300 tests