Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
186 commits
Select commit Hold shift + click to select a range
b404a52
Working: squash of EF-254, EF-295, EF-221, EF-218, EF-253, EF-359, EF…
ajcvickers Aug 24, 2026
1d60893
EF-322: Native LINQ overhaul
ajcvickers Aug 24, 2026
16b0854
EF-322: fix classified native-query bugs and close small native-LINQ …
ajcvickers Aug 25, 2026
9f14651
EF-322: native Reverse/Last/LastOrDefault over an ordered source
ajcvickers Aug 26, 2026
cd2d2c1
EF-322: report spec failures in native mode only when driver mode passes
ajcvickers Aug 26, 2026
b1ad53f
EF-322: native reference Includes: sibling, reference+collection comb…
ajcvickers Aug 26, 2026
260b508
EF-322: native enum casts, conditional expressions and DateTime part …
ajcvickers Aug 27, 2026
cc3f085
EF-322: native whole-root-entity leaf mixed into a projection
ajcvickers Aug 27, 2026
4d6cff4
EF-322: native single-level Join/LeftJoin, join whole-entity leaf and…
ajcvickers Aug 28, 2026
204d310
EF-322: native owned-navigation predicates and projection leaves
ajcvickers Aug 31, 2026
cc2ff77
EF-322: native $concat for string concatenation with non-string operands
ajcvickers Sep 1, 2026
b5c687f
EF-322: native First/FirstOrDefault over a reference-collection navig…
ajcvickers Sep 3, 2026
96903be
EF-322: native collection-then-collection ThenInclude
ajcvickers Sep 5, 2026
9f836ca
EF-322: native scalar aggregate terminating on a bare GroupBy(key)
ajcvickers Sep 5, 2026
11cb931
EF-322: native parameterized string StartsWith/EndsWith/Contains rege…
ajcvickers Sep 5, 2026
0943dcc
EF-322: native equality, Contains and aggregate breadth (projected Di…
ajcvickers Sep 5, 2026
f5c8765
EF-322: recognize and admit the EF8/EF9 internal LeftJoin shim
ajcvickers Sep 7, 2026
181983c
EF-322: native chained join scopes: Where/OrderBy/terminal support
ajcvickers Sep 7, 2026
af207fa
EF-322: trim AGENTS.md files
ajcvickers Sep 7, 2026
c955952
EF-322: native array-parameter element access, reference-Include null…
ajcvickers Sep 7, 2026
add4c6f
EF-322: native literal boolean predicates, filtered collection Includ…
ajcvickers Sep 8, 2026
b9e1b86
EF-322: native Where over a single-level join's Inner scope
ajcvickers Sep 8, 2026
5af4275
EF-322: native operators composed after a projected Distinct, checked…
ajcvickers Sep 8, 2026
7a77aed
EF-322: native ctor-only DTO projection
ajcvickers Sep 8, 2026
ce08581
EF-322: native Distinct and GroupBy-aggregate breadth
ajcvickers Sep 8, 2026
19eb8b1
EF-322: native string-to-char-sequence projection leaves
ajcvickers Sep 8, 2026
76d64f6
EF-322: native null-coalescing operator (??)
ajcvickers Sep 9, 2026
726d246
EF-322: native nested wrapped projection leaf sourced from a join scope
ajcvickers Sep 8, 2026
6add8b3
EF-322: native boolean parameter predicate, computed-key Distinct/Cou…
ajcvickers Sep 10, 2026
4ee6690
EF-322: native GroupBy OrderBy/ThenBy composed before the terminal Se…
ajcvickers Sep 10, 2026
f94e48b
EF-322: native post-Distinct ordering, including computed keys and st…
ajcvickers Sep 10, 2026
f9170f5
EF-322: native breadth wave: GetType, array-Contains, GroupBy variant…
ajcvickers Sep 12, 2026
27b36ee
EF-322: native breadth wave: Equals across mismatched types, composit…
ajcvickers Sep 18, 2026
6728854
EF-322: native chained-join scalar-leaf projection
ajcvickers Sep 22, 2026
033314d
EF-322: native left-outer collection-navigation joins and Skip/Take a…
ajcvickers Sep 22, 2026
909c640
EF-322: native breadth wave: Last without OrderBy, set operations, tu…
ajcvickers Sep 22, 2026
e9757df
EF-322: native OrderBy on a join's Inner scope, boolean ternary and G…
ajcvickers Sep 23, 2026
f4ac42d
EF-322: native multi-arg positional-ctor DTO Select and OrderBy
ajcvickers Sep 23, 2026
95db4c8
EF-322: native 'is' comparison against a non-hierarchy entity
ajcvickers Sep 23, 2026
f1274bc
EF-322: native string.Length accumulator and embedded client-method c…
ajcvickers Sep 23, 2026
fbb8d04
EF-322: native join-scope nav-null-check conditional and bare scalar …
ajcvickers Sep 23, 2026
e414718
EF-322: native EF.Functions.Like and Math translation
ajcvickers Sep 24, 2026
b06ac97
EF-322: native EF8/EF9 reference-Include join scope, conditional ORDE…
ajcvickers Sep 27, 2026
656c5e6
EF-322: native GroupBy fallback reduction (SP1-SP7)
ajcvickers Sep 27, 2026
2cbb406
EF-322: native GroupBy nested-construction projection; fix 12 pre-exi…
ajcvickers Sep 27, 2026
4394b86
EF-322: native reference-collection-nav Count in Where; isolate per-c…
ajcvickers Sep 28, 2026
eedb2e0
EF-322: native string translations phase 1
ajcvickers Sep 25, 2026
fe7cd5a
EF-322: tighten branch-added code comments and AGENTS.md files; fix p…
ajcvickers Sep 28, 2026
3e30bc4
EF-322: native GroupJoin shapes and join correctness fixes
ajcvickers Sep 28, 2026
a1d5192
EF-322: native LINQ coverage for NorthwindAggregateOperatorsQueryMong…
ajcvickers Sep 28, 2026
41d73f9
EF-322: fix wrong-results and crash bugs in native LINQ and driver-LI…
ajcvickers Sep 28, 2026
4bf46ac
EF-322: substitute the key selector for g.Key inside element lambdas …
ajcvickers Sep 28, 2026
bd6cc6f
EF-322: dedup and shape Distinct over a bare join entity leaf correctly
ajcvickers Sep 28, 2026
c1090bb
EF-322: native multi-hop reference-navigation filters (chained join s…
ajcvickers Sep 28, 2026
fe93971
EF-322: native string translations phase 2
ajcvickers Sep 29, 2026
e4e09d1
EF-322: native GroupBy over a join scope; null-ordering guard for agg…
ajcvickers Sep 28, 2026
417f7ad
EF-322: native post-group Where over projected aliases, $push list pr…
ajcvickers Sep 29, 2026
63b4b9e
EF-322: honour configured DateTimeKind in native read-back
ajcvickers Sep 29, 2026
dff92bc
EF-322: suppress SSH.NET audit warnings; tighten comments and AGENTS.…
ajcvickers Sep 30, 2026
2ca7068
EF-322: plans for native Select, SetOperations and Misc spec suites
ajcvickers Sep 30, 2026
445564c
EF-322: native Negate / widening-cast computed projection leaves
ajcvickers Sep 30, 2026
3c20867
EF-322: primary-key string leaves are never null behind a non-nullabl…
ajcvickers Sep 30, 2026
9c20699
EF-322: restrict the primary-key never-null exemption to the root doc…
ajcvickers Sep 30, 2026
a9ee616
EF-322: native null-propagated scalars behind non-nullable types thro…
ajcvickers Sep 30, 2026
c8cde00
EF-322: carry ThrowsOnNull to operators over a flagged alias (Task 3 …
ajcvickers Sep 30, 2026
a61e13a
EF-322: native row-independent projection leaves evaluated client-side
ajcvickers Sep 30, 2026
acc2805
EF-322: native set-operation operand shapes (Union/Concat/Intersect/E…
ajcvickers Sep 30, 2026
039c2d8
EF-322: native client construction over whole-entity operands
ajcvickers Sep 30, 2026
694838c
EF-322: native Misc low-hanging shapes (bool &/|, computed Distinct k…
ajcvickers Sep 30, 2026
140a2d0
EF-322: native Select suite shapes (containers, TimeOfDay, join null …
ajcvickers Sep 30, 2026
4a97787
EF-322: fix silent wrong results and loud-failure gaps found in the o…
ajcvickers Oct 1, 2026
a94662b
EF-322: DRY — reuse shared helpers instead of private copies
ajcvickers Oct 1, 2026
5d48f30
EF-322: DRY — native MQL rendering and pipeline helpers
ajcvickers Oct 1, 2026
5555692
EF-322: fix serialization of composite-key comparisons in GroupBy gro…
ajcvickers Oct 1, 2026
1f846c0
EF-322: DRY — native GroupBy binder helpers
ajcvickers Oct 1, 2026
71d9471
EF-322: DRY — native projection, join-scope and SelectMany binder hel…
ajcvickers Oct 1, 2026
8bce015
EF-322: DRY — MongoExpressionTranslator helpers
ajcvickers Oct 1, 2026
9e22b65
EF-322: DRY — driver-LINQ bridge and projection binding helpers
ajcvickers Oct 1, 2026
757bea3
EF-322: DRY — queryable translator, shaped compiler and materializer …
ajcvickers Oct 1, 2026
740e2e1
EF-322: DRY cleanup — final review fixes (stale comments, visibility)
ajcvickers Oct 1, 2026
022c73f
EF-322: one stored-serialization equivalence rule for anonymous-key j…
ajcvickers Oct 1, 2026
df7adb8
EF-322: one stored-serialization equivalence rule (review fixes)
ajcvickers Oct 1, 2026
694c620
EF-322: native collection Include over multi-level join chains
ajcvickers Oct 1, 2026
05b31cb
EF-322: native collection Include over multi-level join chains (revie…
ajcvickers Oct 1, 2026
e3484e0
EF-322: storage equivalence and multi-level Include — final review po…
ajcvickers Oct 1, 2026
53b3025
EF-322: add plan docs for string null-propagation handoff, DRY cleanu…
ajcvickers Oct 6, 2026
ed0eacb
EF-322: native LINQ parity plan and review findings
ajcvickers Oct 1, 2026
6768480
EF-322: honor MONGODB_EF_QUERY_MODE / MONGODB_EF_NATIVE_ONLY in all t…
ajcvickers Oct 1, 2026
c871c52
EF-322: add native/driver differential test runner
ajcvickers Oct 1, 2026
4c362e8
EF-322: harden native parity runner (abs outdir, missing/odd outcomes…
ajcvickers Oct 1, 2026
b650639
EF-322: parity test helpers for expected-oracle and re-execution checks
ajcvickers Oct 1, 2026
48ccbc2
EF-322: make TwiceWithDifferentValues test prove compiled-query cache…
ajcvickers Oct 1, 2026
82a617e
EF-322: confirm parity scope against upstream main
ajcvickers Oct 1, 2026
20c4c85
EF-322: single strict test query-mode resolver; runner unsets NativeO…
ajcvickers Oct 1, 2026
2dd1394
EF-322: document MONGODB_EF_QUERY_MODE as the suite-wide switch; Twic…
ajcvickers Oct 1, 2026
118068a
EF-322: plan Task 1.11 (F11 non-key correlation); M12 refuted for mai…
ajcvickers Oct 1, 2026
938ffb4
EF-322: principal-side reference Include keeps principals without a d…
ajcvickers Oct 1, 2026
a82db9e
EF-322: serialize null parameters for non-nullable properties as BSON…
ajcvickers Oct 1, 2026
832d8f4
EF-322: evaluate clock members per execution in native plans
ajcvickers Oct 1, 2026
009d3a5
EF-322: throw for non-nullable computed projections over null operands
ajcvickers Oct 1, 2026
7754eeb
EF-322: checked Sum narrowing and serializer-aware Min/Max read-back
ajcvickers Oct 1, 2026
b1c2c1f
EF-322: decline string methods over non-string stored representations
ajcvickers Oct 1, 2026
5b6ee8a
EF-322: decline null-absorbing Math functions over nullable operands
ajcvickers Oct 1, 2026
aba37d1
EF-322: serialize tuple-equality elements through their properties
ajcvickers Oct 1, 2026
b48ecb6
EF-322: missing required scalar in a projection reads default, matchi…
ajcvickers Oct 1, 2026
9b48473
EF-322: explicit BSON null in a bare projection still throws; drop ob…
ajcvickers Oct 1, 2026
72bf562
EF-322: correlated-collection matcher requires the outer principal key
ajcvickers Oct 1, 2026
8147193
EF-322: throw for computed projections over missing non-nullable fiel…
ajcvickers Oct 1, 2026
0149d2d
EF-322: projected Distinct over a computed leaf over a missing non-nu…
ajcvickers Oct 1, 2026
79ed108
EF-322: never fold local-collection filters that read the clock
ajcvickers Oct 1, 2026
df58feb
EF-322: computed projections that evaluate to missing read default, m…
ajcvickers Oct 1, 2026
0456bf2
EF-322: projected Distinct keeps a missing key apart from a null one,…
ajcvickers Oct 1, 2026
a59631e
EF-322: explicit null and missing in aggregate and Distinct reads mat…
ajcvickers Oct 2, 2026
298c792
EF-322: an enum field cast to its underlying type reads a missing row…
ajcvickers Oct 2, 2026
f2417ca
EF-322: join-scope scalars and converted Distinct keys read missing a…
ajcvickers Oct 2, 2026
27e1f61
EF-322: pin alternate-key correlation, wrapped join Min and mixed con…
ajcvickers Oct 2, 2026
6a0df6b
EF-322: record the read-mode stack and Phase 1 invariants in Query AG…
ajcvickers Oct 2, 2026
a399dd8
EF-322: regenerate the NativeOnly gap inventory after Phase 1; plan r…
ajcvickers Oct 2, 2026
c11feff
EF-322: plan for the open-bug triage
ajcvickers Oct 6, 2026
e3e5d2d
EF-446: admit a nested owned-collection quantifier correlated to the …
ajcvickers Oct 7, 2026
57e42f2
EF-322: Add a tiebreaker to the flaky GroupBy computed-OrderBy parity…
ajcvickers Oct 7, 2026
8f79773
EF-322: Fix the compiler warnings
ajcvickers Oct 7, 2026
903da26
EF-322: native translation of scalar functions, collections, owned en…
ajcvickers Oct 12, 2026
31b650a
EF-322: native join with a filtered inner side
ajcvickers Oct 12, 2026
52367a3
EF-322: native aggregates and correlated subqueries over a referenced…
ajcvickers Oct 12, 2026
8a583b7
EF-322: Trim comments and agent docs to non-obvious, forward-looking …
ajcvickers Oct 12, 2026
26f56ac
EF-322: native element leaves over a referenced collection (ToList, F…
ajcvickers Oct 12, 2026
4e9eb4b
EF-322: driver-LINQ bridge parity for aggregates over a referenced co…
ajcvickers Oct 12, 2026
812002f
EF-322: constant Skip/Take on an element leaf; deduplicate the same f…
ajcvickers Oct 12, 2026
ed2f270
EF-322: aggregates over a group correlated on several properties (com…
ajcvickers Oct 12, 2026
2b09bbc
EF-322: align the new code's comments and agent docs with the trimmed…
ajcvickers Oct 12, 2026
b4e3605
EF-322: failing tests for aggregates over a computed element selector
ajcvickers Oct 12, 2026
2bffc78
EF-322: aggregates over a computed element selector (Sum(o => o.Price…
ajcvickers Oct 12, 2026
47dce3e
EF-322: handoff for the referenced-collection follow-ups
ajcvickers Oct 12, 2026
cf2558e
EF-322: remove the superseded 2026-09-25 handoff
ajcvickers Oct 13, 2026
1dafdf5
EF-322: failing tests for element leaves under the driver-LINQ bridge
ajcvickers Oct 13, 2026
cf7ef2a
EF-322: answer element leaves in the driver-LINQ bridge
ajcvickers Oct 13, 2026
7a81f3a
EF-322: failing tests for parameterized Skip and Take on an element leaf
ajcvickers Oct 13, 2026
426bd2f
EF-322: parameterized Skip and Take on an element leaf
ajcvickers Oct 13, 2026
ea17b63
EF-322: failing tests for constant, parameter and computed key parts
ajcvickers Oct 13, 2026
0fb6527
EF-322: constant, parameter and computed key parts in a correlation
ajcvickers Oct 13, 2026
da45545
EF-322: handoff: follow-ups 1, 3 and 4 are done
ajcvickers Oct 13, 2026
9e26edb
EF-322: a scalar aggregate over an aggregate on a referenced collecti…
ajcvickers Oct 13, 2026
6ae1ba1
EF-322: NativeOnly spec baselines for refused translations; fix a sta…
ajcvickers Oct 13, 2026
777b60b
EF-322: name the bridge's native-only lookup refusals on LookupExpres…
ajcvickers Oct 13, 2026
234cc4a
EF-322: move shared binder predicates to neutral homes
ajcvickers Oct 13, 2026
0fd0ee2
EF-322: make the join-scope gate's deferral explicit
ajcvickers Oct 13, 2026
13e0395
EF-322: share Unwrap, UnwrapAsQueryable and the parameter-reference f…
ajcvickers Oct 13, 2026
d27d34d
EF-322: document the derived, recorded and shape flags on MongoSelect…
ajcvickers Oct 13, 2026
56ea941
EF-322: move bulk-write plan building out of the shaped-query compiler
ajcvickers Oct 13, 2026
d2936d7
EF-322: split MongoSelectLowerer.Lower into per-phase methods
ajcvickers Oct 13, 2026
86d6162
EF-322: split the filtered-lookup rendering out of RenderLookup
ajcvickers Oct 13, 2026
1d6ac31
EF-322: split the queryable-method translator into Include, NonQuery,…
ajcvickers Oct 13, 2026
c1f55ad
EF-322: carry a projection binder's staged lookups in PendingProjecti…
ajcvickers Oct 13, 2026
52bec10
EF-322: bind a projection selector through a per-selector session wit…
ajcvickers Oct 13, 2026
764e2b5
EF-322: extract the collection-Include and bare join-scope value arms…
ajcvickers Oct 13, 2026
38c79a1
EF-322: update test comments for the renamed join-scope gate and key-…
ajcvickers Oct 13, 2026
2bb0c82
EF-322: restore API XML doc comments trimmed without a signature change
ajcvickers Oct 14, 2026
ce2a9c0
EF-322: benchmark DriverLinq vs Native on the extended set and record…
ajcvickers Oct 14, 2026
b467e20
EF-322: plan for the wide-dispatch, nested-streaming and Include-besi…
ajcvickers Oct 14, 2026
be5f1bf
EF-322: dispatch streaming element names through a switch instead of …
ajcvickers Oct 14, 2026
a71d56b
EF-322: stream owned-collection elements that own further navigations
ajcvickers Oct 14, 2026
77c626e
EF-322: recognise a reference Include beside owned-sibling includes
ajcvickers Oct 14, 2026
01d76f0
EF-322: record the benchmark-gaps-fixed results
ajcvickers Oct 14, 2026
6ce7f70
EF-322: fix review findings in nested owned-collection streaming
ajcvickers Oct 14, 2026
c66ba97
EF-322: add a steady-state profile loop, async twins and BenchmarkSwi…
ajcvickers Oct 14, 2026
a877c2b
EF-322: read streamed element names through a trie so they allocate n…
ajcvickers Oct 14, 2026
852962a
EF-322: skip the no-tracking "set loaded" call when no ILazyLoader ca…
ajcvickers Oct 14, 2026
c6f2cc0
EF-322: add a 40-property benchmark entity, server-only timing and pr…
ajcvickers Oct 14, 2026
90d5930
EF-322: render a reference Include on the target's _id as $match + $s…
ajcvickers Oct 14, 2026
6e03ce8
EF-322: record the native query path profile, fixes and deferred find…
ajcvickers Oct 14, 2026
fa5b195
EF-322: compare the native profile against main and call the hand-wri…
ajcvickers Oct 14, 2026
cb0bafe
EF-322: add the native perf profiling plan and its handoff
ajcvickers Oct 15, 2026
d0fc0ee
EF-461: decline a native group key or accumulator over a date part of…
ajcvickers Oct 15, 2026
162e4fb
EF-461: expect the two retargeted Northwind GroupBy tests to refuse u…
ajcvickers Oct 15, 2026
ba038d1
EF-464: keep Random.NextDouble/NextSingle/NextInt64 and Guid.CreateVe…
ajcvickers Oct 15, 2026
1d24690
EF-464: log Random.NextDouble/NextSingle/NextInt64 and Guid.CreateVer…
ajcvickers Oct 15, 2026
5b3a173
EF-465: refuse a string, member or arithmetic function computed over …
ajcvickers Oct 16, 2026
c557f44
EF-465: keep string functions of a to-string converted property, pin …
ajcvickers Oct 16, 2026
eb37390
EF-466: refuse a converted bool used as the test of a conditional
ajcvickers Oct 16, 2026
e86b0c7
EF-467: refuse equality or Contains between two operands stored diffe…
ajcvickers Oct 16, 2026
75f46ab
EF-466: also refuse a coalesce of a converted bool as a conditional t…
ajcvickers Oct 16, 2026
e54ec6c
EF-469: read an owned reference and a scalar from the projected docum…
ajcvickers Oct 16, 2026
0ec8782
EF-469: scope the retained-Select alias lookup to the root navigation…
ajcvickers Oct 16, 2026
93dd7b3
EF-472: let a model declare a value-converted property order-preserving
ajcvickers Oct 17, 2026
7b67581
EF-472: close review gaps in the order-preserving declaration
ajcvickers Oct 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
43 changes: 17 additions & 26 deletions .claude/agents/CONVENTIONS.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,34 @@
# Reviewer conventions (shared)

Referenced by every `*-reviewer` agent definition and by `review-ef-core-provider`'s dispatch prompts. This text is intentionally not duplicated in either place — point here instead of restating it.
Referenced by every `*-reviewer` agent and by `review-ef-core-provider`'s dispatch prompts; point here instead of restating.

## Report shape

**Verdict**: one of `approve`, `flag`, `escalate`.
- `approve` = no concerns
- `flag` = non-blocking suggestions or nits
- `escalate` = blocking concern that needs user attention before merge (public-API break, annotation-key rename, behavior change affecting stored documents, multi-EF break, spec-conformance regression, security regression)
**Verdict**: `approve` (no concerns), `flag` (non-blocking suggestions or nits), or `escalate` (blocking: public-API break, annotation-key rename, behavior change affecting stored documents, multi-EF break, spec-conformance regression, security regression).

**Findings**: bulleted list. Each bullet: `<file>:<line> — [fix-in-code|external-action][blocking|substantive|nit] **<TL;DR>** — <one-sentence problem> — <one-sentence fix or action>`.
**Findings**: bulleted, each `<file>:<line> — [fix-in-code|external-action][blocking|substantive|nit] **<TL;DR>** — <one-sentence problem> — <one-sentence fix or action>`. The TL;DR is a bold headline of at most 8 words (e.g. `**Annotation key renamed**`). Use repo-relative paths. At most **5** findings per pass: sort blocking, substantive, nit and drop the lowest rather than padding.

`<TL;DR>` is a terse headline (**≤8 words**), bold, right after the tags. It's a label, not the explanation — e.g. `**May throw NullReferenceException**`, `**Annotation key renamed**`.
Tag 1, who can act:
- `[fix-in-code]`: resolvable by a mechanical in-tree change (edit, add a test, fix a throw type or `#if` branch) without external information.
- `[external-action]`: needs something outside the codebase (JIRA lookup, CI-matrix check, call-site audit outside the diff, `BREAKING-CHANGES.md` wording, or infra you lack: Atlas-only, no `CRYPT_SHARED_LIB_PATH`, multi-EF divergence needing `/test-all`). When unsure, prefer this tag.

Tag 1 — who can act:
- `[fix-in-code]` — resolvable by an in-tree code change (edit, add a test, fix a throw type, fix an `#if` branch) the fixer agent can make mechanically without external information.
- `[external-action]` — needs something outside the codebase: a JIRA lookup, CI-matrix verification, auditing call sites outside the diff, a spec-wording check, `BREAKING-CHANGES.md` wording, or infra you don't have (Atlas-only, encryption without `CRYPT_SHARED_LIB_PATH`, multi-EF divergence needing `/test-all`). When unsure, prefer this tag — it surfaces the concern without claiming the fixer can address it.
Tag 2, importance:
- `[blocking]`: warrants an `escalate` verdict and stops the merge.
- `[substantive]`: a real concern the fixer should address; when unsure between this and `[nit]`, pick this.
- `[nit]`: cosmetic (unused import, typo); safe to defer.

Tag 2 — how important:
- `[blocking]` — should land an `escalate` verdict and stop the merge.
- `[substantive]` — real concern the fixer should address. When unsure between this and `[nit]`, prefer this (conservative — the fixer just acts on it).
- `[nit]` — mechanical cosmetic (unused import, typo, missing trailing newline). Doesn't affect behavior; safe to defer indefinitely.
**Tests run / repros**: every `dotnet test --filter` / `dotnet run` repro you executed with pass/fail, and for each functional finding the repro code plus observed output. `none` if no functional findings and nothing run.

Use repo-relative paths in findings. Emit at most **5** findings per pass — if you have more, sort by tag (blocking → substantive → nit) and drop the lowest-priority ones rather than padding the list.

**Tests run / repros**: list every `dotnet test --filter` / `dotnet run` repro you actually executed, with pass/fail, and — for each functional finding — the repro code/commands plus the observed output (assertion message, exception, or wrong value). Write `none` if you reported no functional findings and ran nothing.

Hard limit: 400 words total, **excluding** repro code/output blocks (those are uncapped).
Hard limit: 400 words, excluding repro code/output (uncapped).

## Verification requirement

A *functional* finding is any claim about runtime behavior — a thrown exception, wrong translation or result, wrong persisted document shape, a behavior-changing `#if` branch, lost `CancellationToken` propagation, a redaction that doesn't fire, etc. — as opposed to a naming/comment/style nit or a source-level signature observation.

You must reproduce every functional finding by running code before reporting it: add a minimal failing test or a small `dotnet run` repro and run it. The functional-test harness (`tests/.../FunctionalTests/Utilities/TestServer.cs`) auto-starts a MongoDB testcontainer via Docker when `MONGODB_URI`/`ATLAS_URI` are unset, so `dotnet test` always runs here with no manual setup — there is rarely an excuse to skip this. If your repro doesn't reproduce the problem, don't report it. Include the repro and observed output in the report (uncapped, doesn't count against the word limit).
A *functional* finding is a claim about runtime behavior (thrown exception, wrong translation or result, wrong persisted document shape, behavior-changing `#if` branch, lost `CancellationToken`, redaction that doesn't fire), as opposed to a naming/comment/style nit or a source-level signature observation.

Only defer to `[external-action]` when a repro genuinely can't run locally: Atlas-only features (e.g. vector search), encryption paths needing infra that isn't installed (`CRYPT_SHARED_LIB_PATH` unset), or a claim of *divergence* across EF8/EF9/EF10 that needs the full `/test-all` matrix. One EF configuration is enough to confirm a behavioral bug on a single version — that must be verified, not deferred.
Reproduce every functional finding before reporting it, with a minimal failing test or small `dotnet run` repro. `TestServer` auto-starts MongoDB containers when `MONGODB_URI`/`ATLAS_URI` are unset (see root `AGENTS.md`), so there is rarely an excuse to skip. If the repro doesn't reproduce, don't report it.

Individual reviewers may narrow or extend this default (e.g. `security-reviewer`'s secret-exposure repro, `vector-search-reviewer`'s Atlas-only exception, `ef-conformance-reviewer`'s multi-EF-divergence exception) — those area-specific overrides live in the reviewer's own file, not here.
Defer to `[external-action]` only when a repro genuinely can't run locally: no Atlas available, `CRYPT_SHARED_LIB_PATH` unset for encryption paths, or a claimed divergence across EF8/EF9/EF10 needing `/test-all`. One EF configuration suffices to confirm a bug on a single version.

**Clean up after yourself.** Delete any file you created to reproduce a finding, leaving the working tree exactly as found. Verifying a finding never means committing a test.
Reviewers may narrow or extend this in their own file.

Reviewers have no `Edit`/`Write` tool — they can never apply a fix, only report one. Any suggested fix is something the parent/fixer applies.
**Clean up.** Delete every file you created to reproduce a finding; leave the working tree as found. Never commit a verification test. Reviewers have no `Edit`/`Write` tool beyond that; fixes are applied by the parent/fixer.
80 changes: 19 additions & 61 deletions .claude/agents/api-stability-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,71 +7,29 @@ model: sonnet

You are the cross-cutting public-API / breaking-changes reviewer for the MongoDB EF Core Provider.

## Authoritative context
The break definition, the "not a break" list (internals regardless of `InternalsVisibleTo`; exception type for unsupported features; native-vs-driver query path and emitted MQL) and the baseline procedure (latest released tag via `gh release list`, never `main` or local tags) are in root `AGENTS.md` ("Versioning & breaking changes"). `BREAKING-CHANGES.md` is the log. A public API added and then changed within the unreleased cycle is not a break: if a symbol is absent at the baseline tag, don't flag it (`git -C "<diff-repo>" show <tag>:<path>`).

Read root `AGENTS.md` and especially `BREAKING-CHANGES.md`. The provider does **not** follow strict SemVer — the major version tracks EF Core's major version (8 / 9 / 10), so even minor-version bumps can carry breaks. That's a policy choice, not an excuse: every break needs to be conscious and documented.
## Surface to watch

What counts as the public surface:
- Anything `public`, or `protected`/`protected internal` on a non-sealed public type: `Mongo*BuilderExtensions`, `UseMongoDB`, `AddMongoDB`, `AddEntityFrameworkMongoDB`, `MongoQueryableExtensions`, `MongoDatabaseFacadeExtensions`, `MongoOptionsExtension`, `MongoDbContextOptionsBuilder`, public enums and attributes.
- `IMongoClientWrapper`/`IMongoDatabaseCreator`/`IMongoTransactionManager`: a new member breaks anyone who implemented them (a default interface method doesn't make it safe to skip the log entry).
- `MongoAnnotationNames` values (serialized into compiled models) and `MongoEventId` numbering.
- Defaults (`AutoTransactionBehavior`, `QueryableEncryptionSchemaMode`, Guid representation, discriminator element name).
- Source-breaking default-parameter changes; visibility tightening; nullability tightening under `<Nullable>enable`; enum renames or numeric changes.
- `[Obsolete]` is for introducing a replacement overload, not for in-place behavior changes (those still need a log entry); confirm the replacement is documented.
- Behavior changes on unchanged signatures: the silent break, often the worst.

- Anything `public` (or `protected` / `protected internal` on a non-`sealed` `public` type).
- All `Mongo*BuilderExtensions`, `UseMongoDB`, `AddMongoDB`, `AddEntityFrameworkMongoDB`, `MongoQueryableExtensions`, `MongoDatabaseFacadeExtensions`, `QueryableEncryptionBuilderExtensions`.
- The `MongoOptionsExtension` and `MongoDbContextOptionsBuilder` types.
- The `IMongoClientWrapper` / `IMongoDatabaseCreator` / `IMongoTransactionManager` interfaces (users are warned not to implement these, but they're observable).
- All public enums: `CryptProvider`, `QueryableEncryptionType`, `QueryableEncryptionSchemaMode`, `BinaryVectorDataType`, `VectorSimilarity` and similar.
- All public attributes: `[Collection]`, etc.
- **Annotation keys** under `Mongo:` — they get serialized into compiled models, so a rename is a hard break.
- `MongoEventId` values — external `DiagnosticSource` subscribers bind by ID.
- Default values for parameters and options (`AutoTransactionBehavior`, `QueryableEncryptionSchemaMode`, etc.) — silent defaults flow into user code.
- Behavior of unchanged signatures — silent semantic shifts are particularly bad here because there's no `[Obsolete]` mitigation for them.
## Pass notes

`InternalsVisibleTo` grants visibility to `MongoDB.EntityFrameworkCore.UnitTests` and `MongoDB.EntityFrameworkCore.SpecificationTests` only (see `MongoDB.EntityFrameworkCore.csproj`). **Changes to anything `internal` are never breaking — regardless of `InternalsVisibleTo`.** That a test assembly can see an internal type does not make it part of the public surface; do not flag internal signature, behavior, or visibility changes as breaks. The public surface is strictly what an external consumer can reference without `InternalsVisibleTo`.
- Report shape and verification: `.claude/agents/CONVENTIONS.md`. Signature, visibility and annotation findings are source-level and need no repro; a behavior-change finding is functional and must be reproduced.
- Run every pass: `git -C "<diff-repo>" diff <base>...<head> -- src/`, and a grep over `MongoAnnotationNames`/`MongoEventId` for renamed, renumbered or removed values.
- Observable change without a `BREAKING-CHANGES.md` update is `[external-action]` (only the user can write the entry).

## Baseline: the latest released version, not `main`
## Escalate to user when

Breaking changes are measured against the **latest released version of the assembly** (the most recent published NuGet package), **not** against the current state of `main`. The practical consequence: a public API that was added, then changed or removed, *within the current unreleased development cycle* (i.e. it does not exist in the last release) is **not** a break — it never shipped, so no consumer depends on it. Only differences observable to someone upgrading from the last released version count.
- Any break to a public type or member, however minor; a behavior change on an unchanged signature; a default change on a public method or `MongoOptionsExtension` property.
- A new member on a public-surface interface.
- A `MongoAnnotationNames` constant is renamed or removed, or a `MongoEventId` member is renumbered, reordered or removed.
- Public surface changes without a `BREAKING-CHANGES.md` update.

**Finding the baseline.** Releases are tagged `v<major>.<minor>.<patch>` (optional `-preview.N`), one line per EF major (`v8.*`, `v9.*`, `v10.*` ship in parallel). Do **not** rely on local `git tag` — a clone's tags are frequently stale and miss recent releases. Use the GitHub release list:
- Absolute latest: `gh release list --limit 1 --json tagName,isLatest`.
- Latest on the EF-major line relevant to the change: the highest non-preview `v<major>.*` from `gh release list --limit 100 --json tagName` (e.g. assess an EF8-only change against the latest `v8.*`).

When in doubt whether a symbol shipped, compare against that tag rather than `main`: `git -C "<diff-repo>" fetch --tags` (if the tag isn't local), then `git -C "<diff-repo>" show <tag>:<path>` or `git -C "<diff-repo>" diff <tag> -- <path>`. If a public symbol is absent at the baseline tag, changing or removing it now is not a break.

## Review focus

- **Signature changes** — parameter type/count, return type, generic constraints, `ref`/`out`/`in` modifiers.
- **Default-parameter changes** — binary-compatible but source-breaking; treat as a break.
- **Visibility tightening** — `public` → anything narrower is breaking. Widening is usually fine but flag types not designed for public use.
- **Removed / renamed / moved public types** — across namespaces too.
- **Interface members added** — breaks existing implementers. The driver's API-stability reviewer notes default interface methods can't help here because the driver multi-targets `net472`; the EF Core provider doesn't have that constraint (it targets `net8.0` / `net10.0`), but `IMongoClientWrapper` and friends explicitly tell users not to implement them, so a DIM on those is moot. New interface members are still a hard break for anyone who did implement them.
- **Annotation-key renames** — `MongoAnnotationNames` values are part of the contract. Renames are breaks for compiled models. Add new keys; don't rename.
- **`MongoEventId` renumbering / reordering / removal** — break for `DiagnosticSource` subscribers.
- **Default-value changes** — `AutoTransactionBehavior` (was changed in 8.1.0), `QueryableEncryptionSchemaMode`, Guid representation, discriminator-element-name behavior. Each historical default-change is in `BREAKING-CHANGES.md`.
- **Exception-type changes** for documented exceptions. **Exception:** changing the exception type thrown for an *unsupported* feature (e.g. a not-yet-implemented LINQ operator, an unsupported mapping, a guard that exists only to reject something the provider does not support) is **not** a break — the thrown type for an unsupported path is not part of the contract. Only the exception type of a *supported, documented* operation matters.
- **Enum value renames / numeric-value changes.**
- **Nullability tightening** under `<Nullable>enable</Nullable>` (the provider has nullable enabled in `src/`).
- **`[Obsolete]` additions** — confirm a replacement is documented. `[Obsolete]` is the tool for introducing a replacement overload, *not* for in-place behavior changes (those still need a doc break).
- **Behavior changes on unchanged signatures** — the silent break category. Often the worst kind.

## Pass discipline

See `.claude/agents/CONVENTIONS.md` for the report shape, tags, finding cap, and default verification requirement. Area-specific notes:

- Most of your findings are source-level (signatures, visibility, annotation keys) and need no runtime check. But any **behavior-change** finding (a silent semantic shift on an unchanged signature, a changed default that alters runtime behavior) is a functional claim and falls under the default verification requirement — reproduce it before reporting.
- The two read-only checks worth running every pass: `git -C "<diff-repo>" diff <base>...<head> -- src/` to inspect every signature change, and a grep over `MongoAnnotationNames` / `MongoEventId` to confirm no values were renamed, renumbered, or removed.
- If observable public-surface behavior changed without a `BREAKING-CHANGES.md` update, tag that as `[external-action]` (only the user can write the doc).

## Escalate to user (do not auto-approve) when

- Any breaking change to a public type / member, regardless of how minor it appears.
- Behavior change of a public method whose signature is unchanged.
- Default-value change on a public method or `MongoOptionsExtension` property.
- New interface member added to any public-surface interface.
- Rename / removal of a `MongoAnnotationNames` constant.
- Renumber / reorder / removal of a `MongoEventId` member.
- Public surface change without a corresponding `BREAKING-CHANGES.md` update (in which case ask the user to add one).

Do **not** escalate (these are not breaks — see the definitions above):

- Changes to anything `internal`, regardless of `InternalsVisibleTo`.
- A public API added and then changed/removed within the current unreleased cycle — it never shipped, so measure against the latest released version, not `main`.
- A change to the exception type thrown for an unsupported feature (unimplemented operator, unsupported mapping, reject-guard). Only the exception type of a supported, documented operation is contractual.
Do not escalate the "not a break" cases listed in root `AGENTS.md`.
Loading