Two-family coordinator proof¶
Issue #3190 requires the Phase 2C proof to enable multiple families together: a successful screening publication must invalidate its declared annotation dependants just as a source-only fallback does. The other optimization and fixture-cleanup suggestions in that issue remain separate follow-ups.
Intrinsic compatibility correction¶
The regression first failed with Incompatible after real annotation and screening writers committed
against the same project. Their rows used different family-specific configuration strings, but the
shared ProjectStatisticsControl.ConfigurationDigest was overwritten by whichever family wrote last.
The reader correctly refused the other family's rows even though the project settings had not changed.
Both threshold types now use one canonical, versioned project-statistics configuration digest. It retains the union of all inputs previously represented by either digest: screening count threshold, nullable agreement ratio, screening overscreening constant, annotation minimum-session constant, and the screening absent-ratio substitute. Family version markers and a project-statistics version prefix identify the format. Formatting is culture invariant, and null remains distinct from minus one. No classification formula, compatibility predicate, transaction boundary or feature flag is relaxed.
This corrects the existing shared configuration authority without introducing another mutable control or per-family migration protocol. Future families must extend this versioned shared input definition or separately specify a different compatibility authority before publication.
Legacy screening.v1 and annotation.v1 rows do not match the new shared digest once a new publication
records it on the project control. Those rows require authoritative rebuild before they can serve
alongside newly published rows; the reader continues to fall back rather than accepting both formats.
The programme remains dark. Backfill and parity for every requested family must pass before enabling
serving. Existing immutable history is not rewritten, and this correction grants no activation approval.
Observable acceptance¶
ProjectStatisticsTwoFamilyProofTests runs against a real MongoDB replica set and uses the production
snapshot factory, family writers, coordinator, repositories and authoritative facet calculators.
Its four cases cover materialized versus capacity-induced source-only commits, each committed and
aborted:
- After ordinary annotation and screening writes, screening, stage annotation, membership-stage annotation and domain reconciliation can be read together and exactly equal authoritative counters.
- A second exclusion crosses the real inclusion threshold. A materialized screening commit keeps its own counters in parity and makes each declared annotation dependant explicitly Stale. A source-only commit also makes screening Stale; mixed requests wholly fall back.
- The source replace uses optimistic version matching inside the same transaction. Source version, receipt, delta (only on materialization), clocks and every affected family's invalidation outbox slot agree with the committed outcome.
- Aborting after both the source write and coordinator work preserves the prior source and Fresh family bundle, creates no operation receipt or delta, and does not advance clocks or notifications.
The bootstrap fixture initializes existing rows; the coexistence assertion follows real family writer calls with their production digests. It does not suppress a digest or substitute a test-only common configuration to make the assertion pass. Administrative authorization is outside this coordinator fixture; its authorization context grants access to isolate publication correctness.
Reproduction¶
From the worktree root:
dotnet test src/libs/project-management/SyRF.ProjectManagement.Mongo.Data.Tests --filter 'FullyQualifiedName~ProjectStatisticsTwoFamilyProofTests|FullyQualifiedName~ProjectStatisticsDependentFamilyTests|FullyQualifiedName~AnnotationParityTests|FullyQualifiedName~ProjectScreeningParityTests|FullyQualifiedName~ProjectStatisticsRebuildTests'
dotnet test src/libs/project-management/SyRF.ProjectManagement.Core.Tests --filter 'FullyQualifiedName~ProjectStatisticsConfigurationDigestTests|FullyQualifiedName~ProjectStatistics.Families'
The original family-specific digests produce four Incompatible failures in the new integration
fixture. With the shared digest, all 49 selected Mongo tests and all 118 selected core tests passed
on 2026-09-05. The Mongo selection includes the four new transaction cases, existing dependent-family
coverage, screening/annotation golden parity and rebuild tests.
This local proof does not replace staged backfill, the consumer performance gates or the required soak.