Table of Contents

Release 2026-09-21

This page is part of the documentation for Orleans.Lattice 9.9.0 (release line 9.9), built 2026-10-04. It is also published as markdown, with every table and list, at 2026-09-21.md, and llms.txt lists every page.

Part of the changelog.

Coordinated lockstep release: 40 packages advance to 9.7.0 - Orleans.Lattice, Orleans.Lattice.Api.Abstractions, Orleans.Lattice.Api.Auth, Orleans.Lattice.Api.Auth.Grpc, Orleans.Lattice.Api.Backup, Orleans.Lattice.Api.Backup.Grpc, Orleans.Lattice.Api.Data, Orleans.Lattice.Api.Data.Grpc, Orleans.Lattice.Api.Mcp, Orleans.Lattice.Api.Mcp.Telemetry, Orleans.Lattice.Api.Mcp.Telemetry.Azure, Orleans.Lattice.Api.Replication, Orleans.Lattice.Api.Replication.Grpc, Orleans.Lattice.Api.Schema, Orleans.Lattice.Api.Schema.Grpc, Orleans.Lattice.Api.State, Orleans.Lattice.Api.State.Grpc, Orleans.Lattice.Api.Telemetry, Orleans.Lattice.Api.Telemetry.Grpc, Orleans.Lattice.Api.TenantAdmin, Orleans.Lattice.Api.TenantAdmin.Grpc, Orleans.Lattice.Api.TreeAdmin, Orleans.Lattice.Api.TreeAdmin.Grpc, Orleans.Lattice.Auth, Orleans.Lattice.Backup, Orleans.Lattice.Backup.AzureBlob, Orleans.Lattice.Caching.AzureBlob, Orleans.Lattice.Dashboards, Orleans.Lattice.GrainIndex, Orleans.Lattice.Membership, Orleans.Lattice.Membership.Entra, Orleans.Lattice.Membership.Entra.Graph, Orleans.Lattice.Membership.Oidc, Orleans.Lattice.Replication, Orleans.Lattice.Replication.Grpc, Orleans.Lattice.Scaling, Orleans.Lattice.Schema, Orleans.Lattice.Storage.AzureTable, Orleans.Lattice.Storage.File, Orleans.Lattice.Tenancy. The Explorer family stays held at 9.4.x, and Orleans.Lattice.Vector, Orleans.Lattice.Api.Mcp.RepoContext and Orleans.Lattice.Api.Mcp.RepoContext.Replication remain unpublished to NuGet and are built from source; entries naming only those packages stay under ## Unreleased until they ship. A package tag shown without a version shipped no NuGet package in this wave.

Added

  • Leaf - Orphaned-leaf audit and repair. An operator can now survey and repair leaves spliced into a sibling chain but unreachable by descent, the state that pins the WAL trim floor indefinitely. Audit is read-only and always registered; repair is opt-in and fails closed on any divergent key. (#3269, #3287) (Orleans.Lattice.Api.Abstractions 9.7.0, Orleans.Lattice.Api.TreeAdmin 9.7.0, Orleans.Lattice.Api.TreeAdmin.Grpc 9.7.0, Orleans.Lattice.Api.Mcp 9.7.0, Orleans.Lattice 9.7.0)

  • WAL - Trim-stop attribution. A pass that reclaims nothing now names why: the trim stop is split into cursor floor, causal frontier and block pin, and the leaf holding the floor has its pin state classified, reporting a verdict the classifier cannot measure as unknown rather than asserting it. (#3042, #3107, #3149, #3155, #3157, #3158, #3168, #3199) (Orleans.Lattice 9.7.0, Orleans.Lattice.Dashboards 9.7.0)

  • WAL - Pass outcomes. Garbage-collection pass outcomes are partitioned per shard and every terminal arm is primed at zero, so an absent series is evidence rather than silence. (#2368, #2768, #2774, #2850, #2938) (Orleans.Lattice 9.7.0, Orleans.Lattice.Dashboards 9.7.0)

  • WAL - Collector liveness. The garbage-collection scheduler publishes its own liveness, a bounded fault backoff, and the consumer count behind a tree's drain lag. (#2433, #3060, #3065) (Orleans.Lattice 9.7.0, Orleans.Lattice.Dashboards 9.7.0)

  • Replay - Concurrency gate telemetry. Ceiling, availability, queue depth and the live withheld-permit level ship as gauges, with a permit queue-wait histogram and every withholding attributed to the trigger that caused it. (#2781, #2784, #2788, #2873, #3044, #3047, #3133) (Orleans.Lattice 9.7.0, Orleans.Lattice.Dashboards 9.7.0)

  • Leaf - Capture telemetry. The snapshot capture path and its cross-leaf concurrency peak are measured, and the silent deferred-terminal drop at the replay-work cap is metered. (#1965, #2278, #2696, #2756) (Orleans.Lattice 9.7.0, Orleans.Lattice.Dashboards 9.7.0)

  • Leaf - Split telemetry. In-flight split completions, faulted attempts, forfeited division fast paths and divisions that were never sought are each positively observable, and the byte-overflow counter is primed at zero. (#2733, #2834, #2846, #2867, #2967, #3053) (Orleans.Lattice 9.7.0, Orleans.Lattice.Dashboards 9.7.0)

  • ANN - Build-sweep telemetry. Each repository the sweep visits records its arming result, a denied corpus announces itself, faults carry a bounded cause, and build slices are dimensioned by repository, space and phase with step progress. (#2252, #2395, #2426, #2441, #2651, #2818, #2855, #2880, #2945, #3130) (Orleans.Lattice.Api.Mcp.RepoContext, Orleans.Lattice.Dashboards 9.7.0)

  • Container - Health and provenance. The container exports runtime, Orleans and heap-ceiling metrics, publishes the silo health verdict and backup-protection state on /metrics, and stamps a build-info gauge proving which checkout it came from. (#2543, #2590, #2621, #2690, #2868, #2980, #3063) (Orleans.Lattice.Api.Mcp.RepoContext, Orleans.Lattice 9.7.0)

  • Memory - Durable backup. Agent memory is backed up to a sink that outlives docker compose down -v, with a tracked deployment runbook and a tuned compose overlay. (#2457, #2601, #2609) (Orleans.Lattice.Api.Mcp.RepoContext, Orleans.Lattice.Backup 9.7.0)

  • Observability - Runtime channels. An uncensored per-grain-type queue-depth channel, a storage gauge that is deterministic across sink instances, and the Orleans and .NET runtime meters on the reference-architecture silos. (#2599, #2605, #2698, #3004) (Orleans.Lattice 9.7.0, Orleans.Lattice.Dashboards 9.7.0)

  • Gates - Metric conformance. Every instrument is held to its documented row and arm arity, each member of an instrumented enum must be armed as a distinct tag value, priming is enforced rather than recorded, and dead instruments are censused. (#2071, #2369, #2506, #2645, #2692, #2730, #2865, #2877, #2889, #2895, #2932, #2939, #2942, #2944, #2950, #2952, #2961, #2988, #3003, #3011, #3054, #3055, #3075) (Orleans.Lattice 9.7.0, Orleans.Lattice.Replication 9.7.0)

  • Gates - Dashboard conformance. Panel tag values, unit suffixes and _bucket references are gated against the instrument that backs them, and the tag-domain resolver can no longer mint a domain it did not read. (#2507, #2508, #2520, #2876, #2920, #2970) (Orleans.Lattice.Dashboards 9.7.0)

  • Gates - Repository-wide guards. The gate list is executable and reports its own executed counts, hygiene gates enumerate tracked files from git, the integration-category gate is enrolled in every test project, and four structural guards ship. (#1877, #2275, #2613, #2627, #2644, #2663, #2718, #2871, #2931, #2991, #3018, #3020, #3052, #3100, #3126, #3142) (Orleans.Lattice 9.7.0)

  • CI - Leg selection and sharding. Content-hygiene gates run for changes that skip the test matrix, a documentation file that is the body of a test selects that test's leg, the integration branch itself is built, and one project is sharded. (#2443, #2653, #2972, #3005, #3021, #3024, #3123, #3134) (repository-wide)

Changed

  • Storage - Binary leaf state. LeafNodeState and leaf snapshots are persisted through a binary grain-storage serializer instead of the default path. (#2481) (Orleans.Lattice 9.7.0)

  • Replay - Off the activation path. WAL replay no longer runs on the leaf activation critical path, its slice width is configurable, merge payloads are shared on the same-silo path, and the ANN sweep cadence is decoupled from reconcile. (#2432, #2459, #2799, #2898) (Orleans.Lattice 9.7.0, Orleans.Lattice.Api.Mcp.RepoContext)

  • Performance - Fan-out and round trips. Shard and partition fan-outs across the tag index, view maintenance, backup restore, bulk load, purge and replication apply now proceed as bounded overlapped waves instead of serial per-entry round trips. (#2144, #2205, #2437, #2472, #2476, #2495, #2532, #2564) (Orleans.Lattice 9.7.0, Orleans.Lattice.Replication 9.7.0)

  • Performance - Hot-path allocation. Steady-state allocation is trimmed across the replication ship and apply legs, CRDT delta coalescing (now linear, not quadratic), tag-index scans, catalog paging, metrics ticks, tenancy snapshots and policy compile. (#2033, #2051, #2065, #2070, #2095, #2214, #2223, #2258, #2309, #2359, #2385, #2595) (Orleans.Lattice 9.7.0, Orleans.Lattice.Replication 9.7.0, Orleans.Lattice.Auth 9.7.0, Orleans.Lattice.Tenancy 9.7.0)

  • Query - Planning without compilation. A Lattice predicate with a captured bound plans without invoking the expression compiler, and a multi-clause grain-index query allocates 91 percent less to intersect its clauses. (#2115, #2118) (Orleans.Lattice 9.7.0, Orleans.Lattice.GrainIndex 9.7.0)

  • Indexing - Converged passes. A converged repository no longer re-probes its whole corpus for embedding gaps on every reconcile, and the reconcile walk and default replication apply path each shed a per-pass steady-state cost. (#2049, #2087) (Orleans.Lattice 9.7.0, Orleans.Lattice.Api.Mcp.RepoContext)

  • WAL - Event-driven collector recovery. The collector now recovers on a registry health signal instead of polling for it. (#3068) (Orleans.Lattice 9.7.0)

Fixed

  • Leaf - Starved checkpoint. A permanently-active leaf could hold rows on which no partition ever reached a durable checkpoint, making nothing durable for a whole process lifetime while every counter reported health. Such a leaf is now driven to a checkpoint instead of reported healthy. (#3079, #3300) (Orleans.Lattice 9.7.0, Orleans.Lattice.Dashboards 9.7.0)

  • Leaf - Orphaned-leaf repair timeout. Driving the whole tree fan-out inside one client-facing call made a repair on a tree carrying hundreds of orphans exceed the client deadline and surface a timeout after it had wholly succeeded. Both verbs now return one bounded batch and a resume token. (#3045, #3059, #3301, #3302) (Orleans.Lattice 9.7.0, Orleans.Lattice.Api.Abstractions 9.7.0, Orleans.Lattice.Api.TreeAdmin 9.7.0, Orleans.Lattice.Api.TreeAdmin.Grpc 9.7.0, Orleans.Lattice.Api.Mcp 9.7.0)

  • Scan - Orphaned leaf off the descent path. A paged range scan walked the sibling chain without checking that the leaf it reached is still reachable by descent, so an orphan duplicated live rows, and its trusted bounds could end a page early and drop them. Each scan now carries a watermark. (#3271) (Orleans.Lattice 9.7.0)

  • WAL - Collector passes. A pass is no longer abandoned wholesale: a reclaimed registry enumerator reconnects and resumes exactly, the collector collects the registry tree it depends on, its backoff no longer starves the trees holding the most WAL, and a timeout is attributed honestly. (#3064, #3073, #3082, #3213, #3238) (Orleans.Lattice 9.7.0)

  • WAL - Durable offset refusal. The collector no longer lets an in-memory consumer cursor alone entitle a trim when a durable materialiser offset floor is reporting and refuses the entry, and the resulting hold is named rather than silent. (#3300) (Orleans.Lattice 9.7.0)

  • WAL - Offset-floor liveness. The repair for a tree stranded behind the durable materialiser offset floor now runs on evidence the tree produces itself, not only when a byte ceiling is configured and breached, and the floor has a liveness bound, so a dormant leaf can no longer pin it forever. (#3094, #3164, #3178, #3186, #3207, #3229, #3265, #3279) (Orleans.Lattice 9.7.0)

  • WAL - Compaction and trim bounds. Compaction, reclaimed-byte and entries-trimmed counters are tagged per shard and primed at zero, so an active minority can no longer mask a stranded majority behind a healthy tree-scoped total. The read path now bounds bytes as well as entry count. (#2689, #2919, #3084, #3206, #3210, #3234, #3242) (Orleans.Lattice 9.7.0, Orleans.Lattice.Storage.File 9.7.0, Orleans.Lattice.Dashboards 9.7.0)

  • WAL - Orphaned pins. Materialiser pins orphaned by leaf reclaim are retired and drained in bulk, a block pin is released and republished when a leaf partition's log is empty, and snapshot_pins can no longer ratchet. (#2695, #2700, #2849, #3057, #3101, #3103, #3105, #3154) (Orleans.Lattice 9.7.0)

  • WAL - Reclamation budget. A tree over its byte ceiling holds the floor instead of backing off, the give-up budget reaches the trees that need it most, a drive that leaves the pin exactly where it found it is no longer credited as a repair, and a warning is throttled per episode. (#2446, #2691, #2710, #2772, #2783, #2815, #3119, #3185) (Orleans.Lattice 9.7.0)

  • Replay - Heap-bounded gate. Concurrent cold hydration and the resident leaf working set are bounded against the heap budget, the gate ceiling derives from the container CPU grant, and a faulted activation no longer leaks its permit. (#2256, #2765, #2767, #2816, #2862) (Orleans.Lattice 9.7.0)

  • Replay - Progress is banked. Cold replay progress is recorded as per-partition snapshot coverage, checkpoint progress survives a cancelled warm replay, the applied prefix is banked on an unappliable entry, and a livelock is mitigated. (#1492, #1831, #2101, #2419, #2668, #2703, #2742, #2746, #2747, #2916) (Orleans.Lattice 9.7.0)

  • Leaf - Snapshot capture. Capture is segmented so no whole leaf is materialised, the row payload is split across grain-state rows, a capture that can make no coverage claim is declined, and a failed load names its real cause. (#2364, #2725, #2753, #2914, #3096) (Orleans.Lattice 9.7.0)

  • Leaf - Hydration and split. Hydration is gated on contiguity rather than total bytes and keeps the leaf frame so a division can still bisect, and uncovered partitions are reset. (#2404, #2769, #2777, #2796, #2836, #2842, #2843, #2844, #2845, #2899) (Orleans.Lattice 9.7.0)

  • Atomic - Torn reads across a reshard. A mid-saga reshard no longer exposes a torn atomic batch: a split pivot outside the leaf's declared span is rejected, the sibling inherits the donor's moved-away seal, and the torn-read invariant is sampled with one atomic read. (#2633, #3117, #3121) (Orleans.Lattice 9.7.0, Orleans.Lattice.Replication 9.7.0)

  • Leaf - Range admission. A B+ leaf no longer admits a write for a key its own declared range excludes, so a row can no longer be admitted in one place and recoverable only from another. (#2137) (Orleans.Lattice 9.7.0)

  • Shard - Root and registry repairs. Slot reassignment is applied atomically, an abandoned shard no longer hands its dirty-leaf list to the next, a leaf that will not compact is skipped so its shard drains, and hot-shard sampling survives a busy shard. (#2262, #2831, #2923, #2926, #3090) (Orleans.Lattice 9.7.0)

  • Scan - Resume and banking. A stall resumes on budget alone and progress replenishes that budget, a stall now stops the walk instead of leaking reads, partial pages are banked, and an unreadable scan-page leaf is detected and recovered. (#2233, #2398, #2456, #2539, #2575, #2618, #2786, #2807, #2809, #2953, #3012, #3016, #3046) (Orleans.Lattice 9.7.0, Orleans.Lattice.Api.Mcp.RepoContext)

  • CRDT - Merge correctness. Batched OR-Flag enables are minted from a fresh dot so an unread row cannot cancel them, the version envelope is stripped from fold state, and LWW tie-breaks order by replica-invariant fields before origin. (#2208, #2795, #2891, #2901) (Orleans.Lattice 9.7.0, Orleans.Lattice.Replication 9.7.0)

  • Serialization - Value equality. Every serializable record, delta and wire DTO carrying a byte[] payload now compares by value, so structurally identical instances, and an instance against its own round-tripped copy, are equal. (#2031, #2047, #2067, #2069, #2116, #2170, #2213, #2475, #2522, #2571) (Orleans.Lattice 9.7.0, Orleans.Lattice.Replication.Grpc 9.7.0)

  • Indexing - Blocked trees. A gate-pruned membership read is no longer promoted to an authoritative coverage digest, a blocked tree is held at the collector's cadence floor, and the blocking consumer is named. (#2464, #2675, #2702, #3041) (Orleans.Lattice.Api.Mcp.RepoContext, Orleans.Lattice 9.7.0)

  • Backup - Readable state. Scope status 0=none is reachable and 3=denied documented, an unstamped origin cluster id is treated as absent in a full capture, and schedule publication ordering is pinned. (#2602, #2640, #2657, #3192) (Orleans.Lattice.Backup 9.7.0, Orleans.Lattice.Api.Mcp.RepoContext)

  • Auth - Policy and fail-open repairs. ExplainAsync cites a target-tree and a cluster-wide rule sharing a rule id, two indexer denial-of-service sites and an Entra fail-open branch are closed, and a URL userinfo credential is redacted. (#2064, #2454, #2479, #2943) (Orleans.Lattice.Auth 9.7.0, Orleans.Lattice.Api.Mcp.RepoContext, Orleans.Lattice.Membership.Entra 9.7.0)

  • Config - Option clamping. Six more extreme-but-permitted background-loop and scheduler cadences are clamped instead of inverting into a silo crash or a busy loop. (#2414, #2455, #2470) (Orleans.Lattice 9.7.0)

  • Schema - Enum transforms. A property, predicate or schema value-transform over an enum with a ulong underlying type no longer throws OverflowException on a member above long.MaxValue. (#2367) (Orleans.Lattice.Schema 9.7.0, Orleans.Lattice.GrainIndex 9.7.0)

  • Core - Dead code. Three unreachable private members are removed, so no dead code advertises a cost or a contract the library never pays or honours. (#2112, #2579, #3239, #3240) (Orleans.Lattice 9.7.0)

  • Dashboards - Panel layout. A gridPos collision on the reliability bucket dashboard is resolved. (#2912, #2941, #3078) (Orleans.Lattice.Dashboards 9.7.0)

  • Storage - WAL page and commit barrier. A WAL read page is bounded by bytes, not only by entry count, the Azure Table provider offers a deterministic phase-two flush barrier, and a reported highest offset can no longer regress. (#1513, #2509, #2528, #2745) (Orleans.Lattice.Storage.File 9.7.0, Orleans.Lattice.Storage.AzureTable 9.7.0)

  • Tests - Fixture repairs. The TTL-preservation fixtures no longer race a sub-second expiry against the saga they exercise, the per-tenant WAL fixture stops driving an internal grain surface, and the tenant-dimension scanner stops false-flagging. (#2070, #2076, #2204, #2629, #2735, #2879, #3249, #3266) (Orleans.Lattice 9.7.0)

  • Docs - Corrections. The inverted WAL-pin contracts, an invalid comparison between two scan-stall counters, the banked=0 attribution on scan-page ceiling outcomes, and the tenant dimension in the panel map are corrected. (#2515, #2585, #2631, #2699, #2793, #2852, #2854, #2864, #2933, #2957, #2997, #3039, #3197, #3212, #3218, #3252, #3256, #3275, #3291) (Orleans.Lattice 9.7.0, Orleans.Lattice.Dashboards 9.7.0)

Security

  • Security - Memory and authorization. Stored agent-memory values carrying a credential-shaped URL or leaked tool-call framing are refused, both effect arms of the authorization decision counter are primed, and four omitted packages are gated. (#2794, #2881, #2994) (Orleans.Lattice.Api.Mcp.RepoContext, Orleans.Lattice.Auth 9.7.0)

  • Security - Credential binding. A discovery-backed JWT authenticator no longer accepts any algorithm the resolved key can carry, a membership cache is no longer keyed on the bearer token alone, and the Explorer binds each credential to one endpoint. (#2416, #2580) (Orleans.Lattice.Auth 9.7.0, Orleans.Lattice.Membership 9.7.0, Orleans.Lattice.Explorer.Entra)

  • Security - Tenant and tree isolation. An unauthenticated cluster client could read and forge every tree, a confined tenant was served global trees on the change feed, and a caller could take over a claimed record by naming its own fencing token. (#2467, #2535) (Orleans.Lattice 9.7.0, Orleans.Lattice.Api.Mcp.RepoContext)

  • Gates - Scan correctness. A gate invoked with a filter matching zero tests no longer exits green, the runner asserts its own population, the em-dash scan no longer walks gitignored directories, and the priming census recognises the idioms and tag domains it had been misreading. (#2498, #2956, #2968, #2996, #3017, #3019, #3033, #3034, #3062, #3067, #3072, #3077, #3080, #3110) (Orleans.Lattice 9.7.0)

  • Replay - Permit admission. Replay permits are partitioned per tree instead of one process-wide semaphore, so one tree backlog no longer monopolises every activation, the ceiling no longer latches permanently on two lost permits, and admission control bounds the wait. (#2883, #2951, #3043, #3066, #3081, #3284, #3290) (Orleans.Lattice 9.7.0)

  • Observability - Priming and attribution. Instruments that reported an unpublished zero are primed, so an absent arm is distinguishable from a measured one; aggregates name the leaf or trigger that produced them; and the runtime meter family is no longer discarded at the listener. (#2365, #2444, #2693, #2694, #2715, #2724, #2770, #2902, #2918, #2940, #3038, #3049, #3058, #3070, #3071, #3085, #3163) (Orleans.Lattice 9.7.0, Orleans.Lattice.Dashboards 9.7.0)

  • CI - Leg and selection repairs. Leg result artifacts are attempt-scoped so a re-run cannot read a stale result, a zero-leg plan no longer skips the vacuity guard, and test selection no longer discards the markdown files that are themselves test inputs. (#2924, #2974, #2985, #3002) (repository-wide)