You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/claude/backlog.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -46,6 +46,7 @@ Real bugs / limitations against shipped behavior — fixes are concrete work, no
46
46
47
47
-**Trailing-space MIN/MAX representative** — for a group of values differing only in trailing spaces (sort-equal under SQL Server), MIN/MAX returns a different byte-variant than the live server's scan-order representative. Surfaced by the AdventureWorks crosscheck on synthetic XML data (`vJobCandidateEducation._max_Edu_Loc_CountryRegion`). Needs trailing-space-insensitive compare + SQL Server's unspecified MAX-tie scan-order. See [`collations.md`](collations.md) "byte-exact sort" trailing-space note. **Deferred** — synthetic data, and the representative is unspecified scan-order on the live side.
48
48
- **Leaked-connection session cleanup** — a `SimulatedDbConnection` that's never `Dispose`d never reclaims its session state: an open transaction holds its locks and pins the MVCC version store, `##temp` tables linger, session-owned app locks stay held, and the SPID accumulates. Real SqlClient's GC-finalization eventually closes a leaked connection and the server resets the session, so this is a genuine fidelity divergence. **Scope correction (2026-07-11): the fix is bigger than "weaken the registry."** Investigation found *three* global strong-reference cycles that pin exactly the connections that hold session state, so GC can't collect them and a finalizer never fires: (1) `LockResource.Hold.Owner` is a strong `SimulatedDbConnection` (reachable Database → table → lock → hold) — pins any lock- or session-app-lock-holding connection; (2) `HeapTable.OwnerConnection` is strong and `Simulation.GlobalTempTables` holds the table — pins any `##temp` owner; (3) `Database.ActiveSnapshotTxs` holds the transaction, which strongly refs its connection — pins any open-snapshot session. Weakening `Simulation.Connections` alone accomplishes nothing because the resource *is* the pin. A correct fix must break all three cycles — cleanest via a one-way `SessionToken` indirection (resources reference a lightweight token identity; the connection references the token, not vice versa) plus a finalizer that enqueues a **deferred teardown** drained on a normal worker thread (next `CreateDbConnection` / version-store GC) so transaction rollback stays off the finalizer thread. This is a broad, mechanical owner-indirection refactor landing on the most regression-sensitive subsystem (lock manager × GC timing × threading). Payoff is bounded (EF disposes scrupulously; only buggy consumer code leaks), so it's **deliberately deferred** as high-risk / low-frequency. Eventual home: [`locking.md`](locking.md).
49
+
- **`SqlLatin1Cp1CiAsCollation.GetHashCode` inconsistent with `Equals` across the repertoire boundary** — the hybrid default collation hashes in-repertoire strings by SQL sort weights but out-of-repertoire strings via its inner Windows collation, so a pair that `Equals` deems equal across the boundary (fullwidth `schema` vs `schema`, the regime-1 fullwidth fold) hashes to different buckets and misses any hash container keyed by the collation. Probe-confirmed divergences (2026-07-13, default collation): real SQL Server resolves fullwidth spellings of user **table / schema / procedure names** (simulator: Msg 208 / "could not find stored procedure" — `Database.Schemas` / `Schema.HeapTables` / `Procedures` dictionary hash-miss), resolves fullwidth **`@variable` references** (simulator: "must declare" — `BatchContext.Variables` hash-miss), and raises **Msg 8143** for a duplicate EXEC named argument spelled `@a` + fullwidth `@a` (simulator: silently binds both — `Simulation.Exec.cs` `seenNames` hash-miss). Column references, named-arg→parameter matching, and `#temp` references already match (linear `Equals` paths). The system-procedure dispatch in `ParseExec` works around it locally (ASCII probes hash consistently with the all-ASCII stored names, so only non-ASCII probes take a linear `Equals` fallback — see `ResolveSystemProcedureName`); that trick doesn't generalize to user-named keys, which can themselves be out-of-repertoire. A general fix means making `GetHashCode` constant on cross-boundary equivalence classes — e.g. hashing everything through the inner Windows collation, which is safe only if weight-equality implies inner-equality for in-repertoire pairs (false collisions are harmless, false splits are not; the ligature/ignorable tiebreaks are the suspect cases) — and needs its own probe-backed bundle since the hash is load-bearing for GROUP BY / DISTINCT / seek caches. `CultureCollation` and the binary collations are self-consistent and unaffected.
49
50
-**Workload-harness divergence reporting quirks** (`.vs/workload/Program.cs`, local-only) — the parity report's example line rebuilds parameters from the op seed and can mismatch the actual divergent instance, and divergent instances aren't re-run single-threaded to classify transient-vs-stable. Both made the 2026-07-10 shared-plan-state hunt slower than it needed to be (the fixed bug class itself — instance-bound aggregate/window results, baked TOP/OFFSET counts, frozen RAND, unstamped replay clock — is documented in [`plan-cache.md`](plan-cache.md)'s shared-plan contract section).
0 commit comments