Domain model, bounded contexts and new aggregates¶
Revised after the owner session (5 October 2026). Chris's owner session of 4 and 5 October changed several parts of this model. The owner-session consolidation wins over older text, and the nine specifications carry the detail. The main changes: a duplicate merge produces one consolidated current Study with immutable history and a reversible unmerge (
StudyMerge,StudyUnmerge,MergeConflictTask,StudyVersion,CurrentEvidenceView; contract C21), which supersedes the alias model; the plannedStudyPoolLedgeris replaced by structuredHistoryEventrecords inpmHistoryEvent(contract C20), and the round-2StudyEnteredPoolis renamedWorkFirstReleased; a stage study filter defines each stage pool and dependencies run only between steps inside a stage; the standard reviewer target lives in the immutable form version (FormVersion.standardTarget) withStudyTargetOverridehistory per Study × form; publication may create attributable generated session versions (D2-01 amended); accepted results areAcceptedResultVersions with four authority values; screening adjudication is anAdjudicationTask; external and AI-model-generated screening decisions enter throughExternalScreeningRunandExternalScreeningDecisionunder aScreeningSourcePolicy(contract C22); and training, the inference beta, contribution exclusion, reversible project deletion, the email content policy, the catalogue and baseline conversion gain their records. Superseded rows are kept and marked "Superseded by the owner session (5 October 2026)". Every name below is aPROPOSALfor the F1a naming ADR. Feature implementation remains on hold (Chris, 5 October 2026). These are planning decisions only. Brief approval and implementation authorisation are separate per gate (D1-04) and still on hold; no work has started, no gate has passed and nothing is enabled in production. The owner-session additions are listed in the owner-session resolution record at the end. Counts and the coverage matrix are in the owner-session integration.Revised after round-2 review (3 October 2026). This version resolves the DD, V2, PH, RT, NS, AP and VB findings that concern the domain model, under the round-2 resolution brief. The main changes: the evidence aggregate is
ReviewerStudyEvidence(study × author scope) rather than one aggregate per answer; the per-project commit sequence is gone;ScreeningOutcomehas candidate and final facets with one writer; the reconciliation task is keyed by study × form; duplicate merge is an alias, never a re-key (superseded by the owner session, 5 October 2026: one consolidated current Study with reversible unmerge, see §4.7 and C21); oneStageaggregate replacesStageSettingsplusStageLifecycle; append-only records are ledgers; and the page now carries a context map, an event and command catalogue, a policy catalogue, shared-kernel value objects and a glossary. Every finding's disposition is in the resolution record at the end.
Temporary planning document; planning only. It brings together the domain model the
contracts imply: the bounded contexts and their relationships, which aggregates exist
today, which the programme introduces, what changes in existing ones, which domain events and commands
exist and where they are hosted, and which release introduces each. It is the logical design.
Physical storage (documents, collections, indexes) is decided by the storage ADR at the engine
freeze F1a (E15), starting from the storage blueprint in
review VB §3. Aggregate, collection
and policy names are PROPOSALs until the naming ADR at F1a fixes them (§13); user-facing terms are
recommendations pending Chris's Batch D answer D3-03 (decided-amended by the owner session: the
meaning of each status is fixed and the exact words may iterate, U1).
Companion pages written in the same revision own neighbouring topics and are cited by file name:
versioning-model.md (version kinds, compatibility, publication rules, append-only repositories and
explicit collection names), consistency-model.md (the commit protocol and transaction table in its
§4, idempotency §5, fences and operations §7, derived records §8, durable effects and events §9,
ordering and as-of §11) and programme-integration.md (the in-flight programmes).
Labels: OWNER (ledger ID or register §1.11 ID), RECOVERED, PROPOSAL, OPEN (Q-xx),
ASSUMPTION (A-xx), CODE-MAIN, CODE-PR. Questions for Chris cite Batch D IDs (D1-xx to D4-xx)
from the resolution brief; this page mints none. Owner-session decisions cite the decision ID, the
consolidation section or the amendment ID (OS-A01 to OS-A30, listed in the
owner-session integration), and the specification rule that details
them (prefixes RD, DM, SP, RS, BC, TI, RI, UX, AC; specification overview).
Code baseline: file and line references marked CODE-MAIN were re-read on main at de3e98c59
(3 October 2026, 14:47 BST). The round-2 reviews read 0f5c61073; the files cited here were not
diffed between the two heads, so a line number taken from a review without re-reading carries the
review's ID instead. Anything not checked is marked UNVERIFIED. Domain types live under
src/libs/project-management/SyRF.ProjectManagement.Core/Model/; aggregate roots derive from
AggregateRoot<TId>; today's collections are named {prefix}{EntityClassName} with pm for project
management (docs/architecture/mongodb-reference.md:88), which §10 replaces with an explicit map.
1. Principles for the new boundaries¶
- A consistency boundary is logical; storage is physical. An aggregate names what one command
must read consistently and may write with one compare-and-set. It does not say how many documents
hold it. The F1a storage ADR decides documents and collections per boundary, within four constraints
from VB's blueprint: revisions are never embedded in sessions (SF3/SF5 share them across forms;
gold and tasks reference them); the full pin map of a session version lives in its own document,
bounded by E28; revisions live in their own collection for the as-of index; Study holds only the
projection. (DD-01, VB improvement 1.)
PROPOSAL. - Study is the per-study serialisation point. Every canonical command that changes study-scoped
evidence or derived state writes that study's Study document in the same transaction: a version
bump plus the
CanonicalSummary(§5). Two commands on one study conflict on Study; commands on different studies share no hot document. (Brief §1.3; consistency-model §4.) - No per-project document in an interactive transaction.
ProjectCommitSequenceis deleted. Within a study, order is the Study version plus per-aggregate versions; across a project, as-of reads use a hybrid logical clock stamp carried by every canonical record (consistency-model §11). Definition-level operations that already run under fences (publication phase 1, binding changes, gold-ownership moves) may keep a project-level sequence. The reason is measured: with one shared per-project document in every save, 399 of 1,000 submissions exhausted their retries at ten reviewers (docs/decisions/ADR-019-materialized-statistics-async-point-fold.md, cited by DD-02 and PH-01; UNVERIFIED here). E25 is settled at F1a on M0 evidence. (DD-02, PH-01, VB-12.) - Immutable history, mutable pointers. Versions, revisions, snapshots and ledger entries are
append-only; a root holds a current pointer changed by compare-and-set. "Never edited" needs a
mechanism, because today's generic save is an upsert replace: append-only repositories, explicit
collection names, content digests and an architecture test (
versioning-model.md, VB-10). Nothing published is deleted (QD1, SL2, GS1); no TTL index on any canonical collection; drafts are removed only by audited discard (D2-13 covers restore; D2-14 covers erasure). Owner session (5 October 2026): D2-13 is a brief item (BC §8.4); D2-14 is amended, so ordinary account deletion disables access and keeps named attribution, and an identity-erasure process is not decided (T-POL-02); permanent physical erasure of a project is an unapproved policy (T-POL-01). The Study parent is the one mutable pointer over its immutableStudyVersions (principle 11). - Every aggregate carries its project ID, except three system-scoped kinds:
Publication(bibliographic identity, with the privacy rule in §4.7),SystemQuestionVersion(one immutable record per question, system version and structural digest; VB-11, VA-09) and system-scopedDefinitionTemplates (the CAMARADES-curated catalogue, D2-15PROPOSAL). System-scoped aggregates are authorised by application role, never by project grants. (DD-25, V2-16, PH-27.) Owner session (D2-15 amended): the system scope is one application-wide CAMARADES catalogue (CatalogueItem,CatalogueItemVersion,catalogueId = camarades) administered by a catalogue administrator application role; project copies carry copy provenance (§4.5; ACD §3.4).AIScreeningModelConfigurationis project-scoped and carries its project ID like any other aggregate. - N-1, and capture rather than ignore. Older binaries tolerate new fields one release before
anything writes them, and they capture unknown elements, as
Entityalready does through[BsonExtraElements](SyRF.SharedKernel/BaseClasses/Entity.cs:21-22,CODE-MAIN), because Study and Project are replaced as whole documents. New fields never go inside persisted computed collections such asSessionTallies, which are rebuilt on every save. R0 also ships the behavioural floor: legacy getters and the claim pipeline merge theCanonicalSummary, inert until a canonical writer exists. (VB-01, VB-02, RT-07.) - Legacy types are frozen for canonical scopes. A
CanonicalScopesmarker on Study and Project is checked by legacy aggregate methods and by a composite registeredIAggregateWriteGuard(src/libs/mongo/SyRF.Mongo.Common/AggregateWriteGuards.cs:17-20,CODE-MAIN), so a legacy write to a canonical scope is a filter miss on the document the writer already compares-and-sets.pmCanonicalOwnershipis the audited registry with a reconciliation check. The legacy embedded model is reached only through the anti-corruption layerLegacyReviewDataAdapter(readers; retired at R7). (DD-05, DD-13, VB-07.) Owner session (R4, OS-A15): every project converts to a faithful baseline in universal waves after pilots, so the adapter has a fixed end at the R7 legacy-writer retirement milestone; the original legacy records stay stored after conversion and are never flattened or deleted (BC). - Append-only facts are ledgers, not aggregates. A record with no invariant beyond "append only,
one writer, ordered" is a
*Ledger, written by the command or operation that produces the fact and ordered by the per-study version (study-scoped) or the clock stamp. (DD-18.) Owner session (OS-A11): new facts that no existing immutable record carries (stage pool transitions, first release of work, review starts, conversion milestones) areHistoryEvents in one append-onlypmHistoryEventstore under contract C20. Existing immutable records stay where they are and are read into the same envelope through adapters. The plannedStudyPoolLedgeris superseded (§4.2). - Every read model declares its consistency regime. Three coexist: in-transaction projection
(
Study.CanonicalSummary, a coexistence adapter retired at R7 with the legacy readers in E20's inventory), eventual materialised rows (FEAT-024) and computed-at-read views (queues, agreement, "Who is offered what", readiness). Each carries a freshness marker (a clock stamp or "authoritative"); gates read only authoritative or fence-verified sources. (DD-17, DD-21.) Owner session: theCurrentEvidenceView(Study.currentEvidence) is an in-transaction projection of a Study's current review associations; it takes over the per-form member list of the canonical summary and its performance and consistency are proved before its design freezes (consolidation §2; DM §3.6). Current stage pools and reviewer study pools are computed at read; history never serves as a second source of current truth. - History explains; it never decides. Structured history (C20) records why a Study entered or left a pool, why a reviewer could start and which versions applied, with effective and recorded time, causal operation and clause evaluations. Admission, selection, counts and readiness never read it. The absence of a record never invents a reason. (Consolidation §3; OS-A07, OS-A10, OS-A11; SP §3.12.)
- Study is a mutable parent over immutable content versions.
Study.state(CurrentorTombstoned) andStudy.currentVersionIdchange only by compare-and-set;StudyVersions, merge manifests and unmerge records never change. A merge or unmerge never edits an input's records. (Consolidation §2; D2-12 replaced; OS-A29; C21.)
2. Bounded contexts and context map¶
The map adopts review DD §3.1 and is frozen at F1a as the first contract ADR (§13). Relationship types: U/D upstream and downstream through a published language; C–S customer and supplier (the supplier accepts amendments from the customer); CF conformist (we adopt the other side's model as is); SK shared kernel (jointly owned types with a joint conformance suite); ACL anti-corruption layer. DD's "Eligibility Results" context is renamed Screening Outcomes here, so that "eligibility" keeps meaning admission (the review eligibility programme's language).
| Context | Root aggregates and ledgers | Owns the language of | Relationships |
|---|---|---|---|
| Review Design (definitions) | QuestionDefinition, SystemQuestionVersion (system-scoped), AnnotationForm, FormVersionIssue, ScreeningProfile (definition side), ProfileVersionIssue, DefinitionTemplate, OutcomeSchema, EntityType (type side), SharedConcept, ProjectRule. Owner session: StudyTargetOverride (versioned Study × form target decisions), DesignDraft with DesignDraftChange, CatalogueItem and CatalogueItemVersion (the system scope of DefinitionTemplate), ClassificationRuleVersion (versions of ProjectRule), TrainingReferenceVersion and TrainingPolicyVersion (definition side of Training) |
question, form, profile, version, issue (the user-facing verb is "publish"), template, compatibility, impact policy; owner session: standard target, override, effective target, generated version, design draft, catalogue, copy provenance | U to Evidence, Workflow, Screening Outcomes, Reconciliation and Reporting (published language: version references and compatibility relations). C of FEAT-024 for usage evidence (C8). SK with Classification for EntityTypeId. U to Training (bound form, profile and reference versions). |
| Review Workflow (stages) | Stage (settings versions, lifecycle, change requests, status history); work-admission decisions (not persisted). Owner session: StageStudyFilterVersion (embedded in the settings version), steps of three kinds (review, system adjudication, training), the stage pool and ReviewerStudyPool (derived, never stored), ReviewStartEligibility (a HistoryEvent payload), pool transition events (StagePoolBaselineMember, StagePoolEntered, StagePoolDeparted) and WorkFirstReleased |
stage, step, route, gate, binding, admission, readiness, lifecycle, capacity; owner session: stage study filter, stage pool, reviewer study pool, exclusion-stop, saved work, continuation, episode, work first released, eligibility explanation | D of Design. SK with the review eligibility programme (ReviewEligibilityPolicy, the facts → policy → decision pattern, IReviewMembershipFacts, the truth table as conformance suite). C of allocation, presence and claims, and batches (C7). Supplies route and admission evidence to Evidence commands. Owner session: D of Screening Outcomes and Reconciliation (filters read current outcomes and accepted answers); writes C20 pool events. The cross-stage route policy (DP6/DP7, Q-15 alternatives) is superseded by the stage study filter (§4.4). |
| Evidence (the engine) | ReviewerStudyEvidence (per project × study × author scope), SessionDraft, ExposureLedger. Owner session: SessionDraftChange (the draft change log), generated session versions (PublicationGenerated, merge kinds), HintExposure and HintAdoption as ledger kinds |
answer, revision, session, save, complete, fix, withdraw, draft, lease, provenance, context, exposure; owner session: draft auto-saved, version checkpoint, generated version, hint, click-to-fill, admission basis | D of Design. SK exports: AnswerContextKey, Provenance, ExposureState, AuthorityValue (split by the owner session, §7.2), the claim key (with presence), the command ledger record (its CommandId doubles as FEAT-024's OperationId, correlation only). CF to AF2 as host, through the F1c extension points. |
| Screening Outcomes | ScreeningOutcome, ProfileAdjudication, StudyPoolLedger (superseded by the owner session, 5 October 2026: HistoryEvent, §4.2). Owner session: AdjudicationTask with AdjudicationVersion (the task aggregate that replaces ProfileAdjudication), AdjudicatorAssignmentVersion, ScreeningDiscussion, AIScreeningModelConfiguration, ExternalScreeningRun, ExternalScreeningDecision |
decision, candidate result, final result, adjudication, pool entry, freshness; owner session: resolution state, final source, outcome composition, tie policy, extra review, Unsure, adjudication step, discussion, AI screening model, AI-model-generated screening decision, source policy (never "model decision") | D of Evidence (decisions) and Design (profile rules and source policies). U to Workflow gates (facets own, candidateCollective, final) and to Reporting. Owner session: CF to the importing user's authority for runs; machine sources are identities, never members (C22). |
| Reconciliation and Accepted Answers | ReconciliationTask (with ReconciliationSession, assignments, editor claim), AdditionalReviewRequest, StudyGold, QueryWorkItem (with ConcernResolution). Owner session: AcceptedResultVersion, the reconciliation presentation mapping, the self-reconciliation override grant (a C10 capability) |
task, candidate, match, accepted (gold), snapshot, concern, resolution, editor claim, held, inputs changed; owner session: accepted result, Single annotator, one-candidate reconciliation, bulk acceptance, below current target, context-local alias | D of Evidence. U to Reporting and Export. CF to the notification stack (C15 v2) and to #3944/#3965 conversations (a clarification channel; StudyConversation moves to this context's lane L6 at R4a). Owner session: U to Workflow (stage filters read accepted answers) and to Classification (collective inference reads pinned accepted results). |
| Classification and Populations | AnimalPopulation, EntityType instances (label heads in Evidence), InferenceResult. Owner session: the project's inference beta setting (off by default, explicit project-designer opt-in) and InferenceResult keyed by basis, rule vector and engine version, with history |
population, cohort, instance, concept, rule, assertion, inference; owner session: inference beta, basis (own snapshot or pinned accepted result), superseded, withdrawn | SK EntityTypeId with Design (identities minted at F1a). D of Evidence. Owner session: D of Reconciliation for collective inference. |
| Identification and Deduplication | Publication (system-scoped), Citation (immutable record on Study), StudyAlias (on Study; superseded by the owner session, 5 October 2026, see §4.7), DuplicateReviewItem, DedupAuditLedger, StudyLifecycleLedger, ExternalStepLedger, dedup batch staging. Owner session: Study state and tombstone, StudyVersion (field provenance, reference and source-document links), StudyMerge with its manifest, MergeConflictTask, StudyUnmerge, CurrentEvidenceView |
citation, record, publication, duplicate, primary and secondary study (superseded: consolidated Study and input Studies), source, retrieval, external step; owner session: reference, source document, consolidated Study, tombstone, unmerge, carry-forward, field origin, distinct report | CF to FEAT-011 and FEAT-012 with the amendment change policy. S to Reporting. C of the PDF programmes (retrieval events, amendment M) and the deletion-lifecycle programme (withdrawal, D3-12). Owner session: U to every evidence context through merge provenance; writes C20 events through C21. |
| Reporting and History | PrismaFlowSnapshot, PrismaPhaseMapping, ExportManifest, DataExportJob, AgreementResult (own rebuildable store, D3-11). Owner session: the HistoryEvent envelope and its queries (C20), ProtocolRegistration with its amendment log, search documentation versions on SystematicSearch |
report (PRISMA flow), manifest, coverage, as-of, watermark, agreement; owner session: reviewed through the stage, ever in the pool, report identity coverage, machine-assisted share | D of everything. Never writes review data. Owner session: reads pool history as audit data; actual review through a stage is the reporting priority (T-SI-05). |
| Membership and Permissions | Project (root), groups, grants, delegation envelope, invitations, join requests; DisclosurePolicy. Owner session: ContributionExclusion and ContributionExclusionLift, Project.deletionState with ProjectDeletionRecord and ProjectRestorationRecord, the catalogue administrator application role, training admission through group membership |
member, group, grant, capability, delegation, disclosure, owner; owner session: contribution exclusion, deleted project, restoration, named attribution | CF to authorization #3335 (evaluator, audit, catalogue, membership schema 1). Supplies DisclosurePolicy to every other context and every channel (reads, exports, statistics, notifications, presence). Needs X-AUTH-RESOLVER (#3251) for out-of-request evaluation. |
| Platform and Coexistence | CanonicalEnrolment, CanonicalOwnership (registry) plus per-document CanonicalScopes markers, command ledger records, operation records, LegacyWriteLedger, LegacyIdAlias, compatibility floor. Owner session: baseline conversion records (inventory, manifest with the legacy activity mapping, wave, parity report, quarantine, recovery manifest) and firstCanonicalWriteAt on the registry |
enrolment, ownership, scope, floor, operation, fence, lease, generation; owner session: baseline conversion, wave, quarantine, legacy-gap state, first canonical write | ACL LegacyReviewDataAdapter toward the legacy embedded model: readers only, writes refused by ownership, retired at R7. Hosts the ADR-020 operation pattern for every context. |
| Notifications (programme-owned) | InboxNotification, NotificationFanOut, NotificationEmailPreferences, NotificationEmailDelivery, NotificationEmailDigest. Owner session: NotificationContentPolicy, per-project email mute, notice resolution |
kind, occurrence, recipient, capture (inline, recorded fan-out), digest, halt; owner session: content policy, mute, resolution | U programme. Every context is CF to C15 v2; the kind registry is the extension point; one capture service is the only writer. |
Training (new, owner session PROPOSAL) |
TrainingAttempt (with training sessions under author scope training(attemptId)), TrainingAssessment, admission and promotion records; TrainingStep is a step kind of the Stage aggregate |
training step, reference answers, attempt, assessment, pass, retry, admission, promotion | D of Design (reference, policy, form and profile versions) and Workflow (the step). CF to Membership for group admission. Never U to Reporting: training records are never PRISMA, target or accepted-result inputs (S4; TI). |
2.1 In-flight programmes¶
Details, timing and PR slicing are in programme-integration.md; this table fixes the relationship
type the domain model assumes.
| Programme | Relationship | Through |
|---|---|---|
| FEAT-024 materialised statistics (ADR-018/019) | C–S (we are the customer) | A FEAT-024-owned source-write seam with a projection-only shape; new families and scope kinds by FEAT-024 amendment at F2/F5; the engine never writes statistics or pending entries itself; canonical CommandId = OperationId (correlation only); ADR-019 gate (b) shape for the canonical write gate (D1-08) |
| Proportional allocation (FEAT-025) | C–S | StageAllocationRegime referenced by ID from StageSettingsVersion; refused on canonical stages until AL1 (D3-13a); regime schema v2 at AL1 with its floor |
| Progressive batches (#3936/#3939) | C–S | Batch plan referenced by ID; IStudyObligationEvidence seam; shared opening and personal grant are durable transitions that write StudyPoolLedger (AP-05). Owner session: they write the first release as a WorkFirstReleased HistoryEvent; batch membership is defined over stage pool episodes (SP §3.7) |
| Active reviewer tracking and presence | SK (claim identity) | Claim contract v2 (§4.11); presence and connection records keyed by form; the draft lease shares the stable tab ID but works with tracking off; X-CLAIMS and X-RECLAIM. Owner session: connections are tracked separately and one shared place serves every tab and route (D2-08); the form owns the inactivity timeout (D2-07); tracking at project scope is a PROPOSAL (SP-AMB-12) |
| Review eligibility programme (paused) | SK | ReviewEligibilityPolicy extended by WorkAdmissionPolicy; IReviewMembershipFacts extracted now; the generated truth table is the conformance suite (D3-09). Owner session: D3-09 is a brief item that aligns the paused programme with the filter, step, exclusion-stop and preserved-work rules; the truth table gains filter, step, exclusion-stop and continuation columns and drops the cross-stage columns |
| Authorization #3335 | CF | ProjectAuthorityEvaluator, authorizationAudit, the catalogue, membership schema 1; X-AUTH-RESOLVER |
| Notification stack (#3932–#3947, #3965) | CF | C15 v2 capture contract; kind registry; Source sub-document; per-project notification admission as an enrolment scope (NS-04, D3-21) |
| AF2 and reviewer layouts | CF (host) | F1c extension points; VersionedAnnotationFormDataSource; Needs-updating presenter; layout-contract amendment; canonical routes never fall back to AF1 |
PDF programmes (bulk PDF upload, PDF Agent, #3947 checked PDFs, StudyPdfCorrection) |
C–S | Retrieval events for P1 (amendment M); their Study writers are inventoried (NS-08) |
| Deletion lifecycle (ADR-014) | C–S | Withdrawal hides Studies but keeps Citations and canonical evidence; whole-project deletion keeps ADR-014's removal with a tombstone that covers the canonical collections (D3-12). Superseded by the owner session (5 October 2026), see §4.13: ordinary project deletion is reversible (Project.deletionState, restoration through a restricted Deleted projects view); permanent physical erasure is a separate unapproved policy (T-POL-01). The uncommitted deletion design labelled "ADR-014" needs a new ADR number because ADR-014 is already the study PDF viewer |
| Identity | CF | Canonical records store opaque investigator GUIDs only; erasure anonymises the Investigator record (D2-14, VB-19). Superseded by the owner session (5 October 2026, D2-14 amended): ordinary account deletion disables access and keeps named attribution; opaque GUIDs are kept so that a future process stays possible; an identity-erasure process is not decided (T-POL-02) |
| Study Management (FEAT-018) | C–S | Library placement for dedup queue, merge wizard and source classification (PH-31); study issues move to this programme (NS-19). Owner session: the merge wizard covers preview, conflict tasks, delegation, commit and unmerge with carry-forward choices (DM) |
3. Today's domain model¶
Corrected per V2-15 and RT §5.1. "Where" is the folder under Core/Model/ unless stated; roots at the
folder root are called out because the folder-per-aggregate convention does not hold.
| Aggregate root (collection) | Where (CODE-MAIN) |
Holds | Relevance to this programme |
|---|---|---|---|
Project (pmProject) |
ProjectAggregate/Project.cs:25 |
Embedded AnnotationQuestion list; Stage entities (review mode, grouped configuration, workload shares, allocation pointer, stage security; ProgressiveBatches once #3939 merges); memberships; security settings and groups; invitations; join requests; keywords; agreement thresholds; embedded job records (search import, bulk study update, bulk PDF upload, risk of bias); SystemQuestionVersion |
Root of Membership and Permissions. Questions and canonical stage settings move out; the four embedded job records stay (A-30). Owner session: gains deletionState for reversible deletion (§4.13) |
Study (pmStudy) |
StudyAggregate/Study.cs:16 |
Bibliographic data; ScreeningInfo; ExtractionInfo (sessions, annotations, outcome data, computed tallies); SlotReservations (:215; natural key investigator + stage, SlotReservation.cs:12); bulk-update lock; PendingStatistics and StatisticsFoldSequence (:148-162); risk-of-bias info; PDF paths |
Gains CanonicalSummary, CanonicalScopes, the alias set and the claim set v2 (§5). Its embedded legacy types are frozen for canonical scopes. Owner session: the alias set is superseded; Study gains state, currentVersionId, tombstone, consolidatedInto, currentEvidence and, in the canonical summary, filterInputs[] and stagePoolTracking[] (§5) |
SystematicSearch (pmSystematicSearch) |
SystematicSearchAggregate/SystematicSearch.cs:10 |
Name, description, reference files; NumberOfStudies is computed from the reference files (:42), not a citation count; schema version kept in extra elements (:118-137); living-search link |
Gains source type and name, withdrawal state, external-step references and, if D4-05 is approved, search documentation fields |
Investigator (pmInvestigator) |
InvestigatorAggregate/Investigator.cs:27 |
Account and profile | Unchanged; erasure extends to canonical records (E32, D2-14). Superseded by the owner session (5 October 2026): DeactivateAccount() stays the ordinary behaviour, named attribution is retained and no anonymisation runs; identity erasure is not decided (T-POL-02) |
InvestigatorUsage (pmInvestigatorUsage) |
InvestigatorUsageAggregate/InvestigatorUsage.cs:9 |
Usage and favourites | Unaffected |
| InvestigatorEmail (view) | InvestigatorEmailsView/InvestigatorEmail.cs:5 |
Email read model (AggregateRoot<string>) |
Unaffected |
Potential (pmPotential) |
PotentialAggregate/Potential.cs:7 |
An invitee keyed by email with invitation IDs | Unaffected (NS-25's duplicate invitation mail is the notification programme's) |
DataExportJob (pmDataExportJob) |
DataExportJobAggregate/DataExportJob.cs:26 |
Export jobs and summaries | Previous-version and as-of modes, manifest reference, D11 download ownership |
StudyPdfCorrection (pmStudyPdfCorrection) |
StudyCorrectionAggregate/StudyPdfCorrection.cs:9; repository Mongo.Data/Repositories/StudyCorrectionRepository.cs:12 uses the generic base, so the class-name formula applies |
PDF correction requests (pending, PDF replaced, original kept); raises StudyPdfCorrectionApprovedEvent |
A Study writer on approval (PDF path), inventoried for R0. docs/architecture/mongodb-reference.md:103 still lists pmStudyCorrection/StudyCorrection: stale, corrected in the F1a docs PR. "Correction" is reserved in the glossary (§8) |
RiskOfBiasAiJob (pmRiskOfBiasAiJob) |
RiskOfBiasAiJobAggregate/RiskOfBiasAiJob.cs:18 |
AI risk-of-bias jobs (dormant tool) | Writers inventoried |
ProjectDailyStat (pmProjectDailyStat) |
ProjectDailyStatsAggregate/ProjectDailyStat.cs:6 |
Daily statistics | Unaffected |
StageAllocationRegime, StageAllocationRegimeTransition (pmStageAllocationRegime, pmStageAllocationRegimeTransition) |
AllocationRegimeAggregate/StageAllocationRegime.cs:39, StageAllocationRegimeTransition.cs:11 |
Immutable regime record, transition log, pointer on the embedded Stage, startup compatibility check | Referenced by ID from StageSettingsVersion (AL1). The regime pattern (immutable record, transition log, pointer, compatibility check) is the template for settings versions and batch plans |
ProjectStatistics family (pmProjectStatistics*) |
abstract root ProjectStatisticsAggregate/ProjectStatisticsDocument.cs:18; receipts ProjectStatisticsSourceOperationReceipt.cs:20 |
FEAT-024 rows, source-operation receipts, publication operation, guard, manifest and marker | New families by FEAT-024 amendment; FEAT-024 receipts are not the canonical idempotency authority (VB-04; consistency-model §5) |
ReviewerPresence (pmReviewerPresence) |
Model root, ReviewerPresence.cs:24; one current presence per (investigator, stage) (:11); AnnotationSessionId points at the embedded session (:87); kept indefinitely (:8-9) |
Engagement windows, suspension, dirty marker | Gains FormSessionId (additive), a form-keyed current-presence index (create, read both, drop), disclosure-shaped snapshots and a retention rule (E32) |
ReviewSessionConnection (pmReviewSessionConnection) |
Model root, ReviewSessionConnection.cs:15; AggregateRoot<string> keyed by the SignalR connection ID; (study, stage, investigator) index (:12-13); HasStartedAnnotating (:59) |
Connection to review context, heartbeat, stale-check token | Gains the stable client tab ID shared with the draft lease and a form key beside StageId; "dirty" becomes the draft-changes flag |
ReviewerWorkspaceSettings (pmReviewerWorkspaceSettings) |
ReviewerWorkspaceSettingsAggregate/ReviewerWorkspaceSettings.cs:5 |
Per-reviewer Dockview layouts per capability slot | Layout-contract amendment at F1c |
| BulkPdfUploadReleaseRecord, BulkPdfUploadQuarantineFence, BulkPdfUploadStorageBinding | Roots inside ProjectAggregate/ (:13, :7, :11) |
Bulk PDF upload authority, quarantine and storage records | Study writer at finalisation (Study.MarkBulkPdfDelivered, Study.cs:189-206), inventoried; retrieval-event source for P1 (amendment M) |
ADR-020 bulk update stores (pmBulkStudyUpdateOperation, pmBulkStudyUpdatePlan in chunks of 100, pmBulkStudyUpdateBeforeImage) |
Core/Services/BulkStudyUpdate/Atomic/ (not Model/); explicit collection names per mongodb-reference.md:107-109 |
Operation record (lease, generation, phase, manifest), validated plan chunks, before-images with TTL | The operation-record pattern (lease, generation fencing, plan chunks, lock, apply, release) reused for publication phase 2, projection rewrites, adoption cutover and merge/split (§4.9) |
M5b risk-of-bias run stores (pmRobRunOperation, pmRobRunBeforeImage) |
Core/Services/RiskOfBiasAssessment/Atomic/RobRunOperation.cs; store Mongo.Data/RiskOfBias/MongoRobRunStore.cs; names per mongodb-reference.md:110-111 |
All-or-nothing batch run; ActiveSearch unique partial index serialises runs per search |
The "one active operation per scope" index reused for one active FormVersionIssue per form |
Claim-revocation outbox (pmActivityClaimRevocationOutbox) |
Core/Services/ReviewEligibility/Revocations/ActivityClaimRevocationIntent.cs:26 (not a root); TTL 7 days on delivered intents (mongodb-reference.md:106) |
Durable intent for the targeted claim-revoked event | The leased, idempotent dispatcher pattern for C19 class (b) effects |
pmPublication |
Planned only (mongodb-reference.md:112) |
— | Introduced by this plan (§4.7) |
Embedded, not roots: Stage, AnnotationQuestion, memberships and groups, the four job records,
SlotReservation (Entity<Guid>, SlotReservation.cs:23), Screening, AnnotationSession,
Annotation, OutcomeData, StudyPendingStatistics.
PR-only (CODE-PR, per notifications integration and review NS):
InboxNotification (pmInboxNotification), NotificationEmailPreferences, NotificationEmailDelivery
(the delivery ledger), NotificationEmailDigest, ImportNotificationAdmission, StudyConversation,
StudyIssue, CheckedPdfProposal with its file record (#3932–#3947, #3965); the progressive batch
plan, membership and access collections and Stage.ProgressiveBatches (#3939).
R0 writer inventory. Every root above that writes Study belongs in R0's legacy-writer inventory
(migration §1.4): PDF-correction approval, bulk PDF
finalisation, ADR-020 bulk update, M5b runs, the FEAT-024 fold, the tracking writers (RT-08), #3945
study issues and #3947 checked PDFs (NS-08), and every UpdateMany on pmStudy.
Mongo.Data.Tests/StudyWriteLockArchitectureTests.cs:81-90 already names
UpdateStudyInclusionInfoForProjectAsync and RemoveAnnotationsFromStudiesInProjectForQuestionAsync
among the known writers (CODE-MAIN).
4. New aggregates and ledgers by context¶
Release columns use the integrated plan's names. Collection names are the explicit map in §10, not class names.
4.1 Evidence¶
| Aggregate, entity or ledger | Key and contents | Key invariants | Introduced |
|---|---|---|---|
ReviewerStudyEvidence (one logical aggregate; physically pmFormSession, pmFormSessionVersion, pmAnnotationHead, pmAnnotationRevision per VB's blueprint) |
Key (project, study, author scope). Author scope is candidate(investigatorId) here; the reconciled scope's heads belong to StudyGold (§4.3) and the imported scope (D4-14) and policyDerived provenance are revision attributes, not scopes. Entities: FormSession (deterministic ID from (project, study, form, author); status derived from the latest explicit version; presentation state in a separate per-session document); FormSessionVersion (Save, Complete, Fix, Withdraw or policy-derived; pinned form version seq; full pin map in its own document; route stage and step; exposure state; the (ProjectId, CommandId) unique key makes it the command ledger record); AnnotationHead (context key plus contextKeyHash; kind: ordinary answer, screening decision, decision-owned answer, later classification assertion and observation; current revision pointer; Conflicted state for adopted duplicates); AnnotationRevision (immutable typed payload, question version reference with AuthoredUnder = Unknown allowed, parentRevisionRef and owningParent edges, provenance, clock stamp, command ID, real actor, content digest) |
One head per context per author scope (local). Current pointers change by CAS on the aggregate version. A version pinned by gold or a task is never deleted (the one cross-aggregate read, at withdraw). Session effective state is derived on read from (latest explicit version, its pin map, current published version, recorded policies, per-answer validity); never stored as a flag (D2-01). Publication writes no evidence except Q-34 option mapping, which writes policy-derived revisions with provenance (superseded by the owner session, 5 October 2026, D2-01 amended: publication may create attributable generated session versions of kind PublicationGenerated under the generation table in RD §3.15 and versioning model §8.11; a generated version is attributed to the publication operation and the publisher, keeps the reviewer as effective author of the answers, never records a Complete that fails validation and never overwrites a newer reviewer version; Q-34 mapping is decided and writes new immutable revisions; where no version is generated, standing stays derived). A Save under a superseded form version is pinned to the version its client declared, never rebased (owner session: where a version was generated, a late Save is refused as stale and the draft is rebased, RD-R24). SF3/SF5 sharing and SF1 reuse are intra-aggregate. PROPOSAL (DD-01). Owner session: version kinds also include MergeResolved, MergeCarriedForward and UnmergeCarriedForward (C21); every explicit version and decision revision carries admissionBasis (InPool, ContinuationAfterExclusion, ContinuationAfterDeparture; SP §3.8) and records the declared form version, which fixes the outdated-answer completion mode (RS-R41); author scope training(attemptId) holds training sessions, which every live query excludes (§4.12) |
R2a (one stage), R2b (several stages), R2d (cross-form sharing), R3a (screening decisions) |
| ProfileSession (entity of ReviewerStudyEvidence) | Key (project, study, profile, author), deterministic ID; versions are decision submissions (DP3), with the same Save/Complete/withdraw mechanics as FormSession; the decision head and its decision-owned answers hang off it | Gives screening-only steps a session and draft container (V2-18). The shape is fixed at F3 (routing) and F5 (profiles). PROPOSAL. Owner session: profile publication may generate attributable profile-session versions where the admin's Q-26 treatment carries decisions forward or requests renewal (RD §4.12); merge-resolved decisions are MergeResolved profile-session versions (C21) |
R3a (default profile), R3b |
SessionDraft (pmSessionDraft) |
Key = session ID (form session, profile session, or the task's reconciliation session); base explicit version; content stored as patches against the base; lease (holder's stable tab ID, etag, per-holder write sequence, heartbeat); bounded conflict copies retained N days; audited discard record; size cap tied to E28 | One draft per session, CAS against the base. A non-holder's edits become a conflict copy ("keeps both" is literal, AC-R2a-06). "Take over editing" transfers the lease (D2-08). Save and Complete present the draft etag and consume the draft atomically. A stale autosave arriving after a newer explicit version is rejected. A duplicate write sequence is success. Never written in a Study transaction. No TTL; retention only by audited discard. Whether a draft holds the reviewer's place: D2-07 (recommended middle ground). PROPOSAL (DC-07, VA-12, VB-15, RT-10). The lease, take-over and middle-ground clauses are superseded by the owner session (5 October 2026), see RD §3.10, §3.11: autosave sends diffs with per-answer base checks and each accepted change appends a SessionDraftChange ({draftVersion, basedOnDraftVersion, per-answer base, patch, connectionId, tabId, actor, at}, append-only pmSessionDraftChange), so the draft history is fully reconstructable (replaces PH-33's "no autosave trail"); two tabs or devices may autosave and a change to an answer that moved since its base becomes a recoverable conflict copy (D2-08 decided; a read-only take-over presentation is a brief detail); a draft whose base was superseded (by a generated version or the reviewer's own Save in another tab) is rebased, non-overlapping changes apply and nothing is discarded silently (RD-R24); the form owns the inactivity timeout and the per-reviewer in-progress limit, one idle tab never releases the place while another connection is active, and expiry releases the place and keeps the draft (D2-07 decided) |
R2a |
SessionDraftChange (pmSessionDraftChange, append-only; owner session) |
Key (session, draftVersion). {draftVersion, basedOnDraftVersion, per-answer base, patch, connectionId, tabId, actor, at}; linked to the explicit version that consumed it |
Immutable; written with the draft head CAS on draftVersion; never written in a Study transaction; the draft rebuilds byte for byte from its base and the log; retention and compaction are brief items and compaction never removes an explicit version (consolidation §1; RD §3.10; RD §12 ambiguity 1, recommendation: keep every accepted change) |
R2a |
ExposureLedger (pmExposureLedger) |
Append-only: session version, revision or thread shown, kind (acceptedRevisionShown, questionedInReconciliation per NS-06), time, clock stamp |
Deduplicated per (session version, revision). A lost report never turns informed work into independent work (C3). Exposure arrives in the draft, Save and Complete REST payloads, never over the presence hub (RT-26). The questioned kind is looked up by session from #3965's record. Owner session: new kinds reconciledHintShown (HintExposure, written when a hint renders in view) and reconciledHintAdopted (HintAdoption, written when the reviewer clicks to fill; the written revision carries adoptedFrom), the screening discussion exposure, and trainingReferenceShown for training feedback. An adopted answer counts toward qualification and is never an independent observation (RS-R31 to RS-R38; OS-A04). No new collection |
R4a |
4.2 Screening Outcomes¶
| Aggregate or ledger | Key and contents | Key invariants | Introduced |
|---|---|---|---|
ScreeningOutcome (pmScreeningOutcome) |
Key (study, profile), deterministic ID. Current value object ScreeningOutcomeValue {candidateResult, voteCounts, ruleVersion, finalResult, finalSource, adjudicationRef?, freshness}; the DefinitionVersionVector it was evaluated under; append-only history entries with clock stamps |
One writer: CollectiveOutcomePolicy, invoked by the submit, correction, adjudication and sweep commands. Candidate and final facets are separate; every reader names the facet it gates on (own, candidateCollective, final). A rebuildable projection with a parity fixture (VA-20). Readers compare vectors; admission fails closed on a stale vector; predicate-driven sweeps repeat until clean (DC-08). A collective Excluded stays Excluded despite extra extraction (PR1). Authority values per amendment H (superseded by the owner session, 5 October 2026: outcome provenance is finalSource ∈ ProfileRule, Adjudicated, MergeResolved plus RI's composition fields machineContribution ∈ {None, Contributing, Sole} and externalHumanContribution; no LegacyUnknown, Q-35 removed; RS §3.8, RI §3.13). The current value is projected into Study.CanonicalSummary.screeningOutcomes[] (FEAT-011's stored name, one array; the summary element is ScreeningOutcomeSummary, V2-17). PROPOSAL (DD-06; shape at F1a, frozen with amendment H at F3). Owner session: the value gains resolutionState ∈ Pending, AwaitingExtraReview (with the remaining bound), InDiscussion, PendingAdjudication, Included, Excluded; only the last two are definite; evaluation is order-independent over the multiset of current applicable decisions under the profile version's sufficiency, Unsure and tie rules (RS-R44 to RS-R51); Unsure is not excluded for availability and never a definite Include; a collective all-Unsure state waits for the brief (RS §5.10). An adjudicated final facet stays current, flagged InputsChanged, when its inputs later change, until an eligible adjudicator explicitly reconsiders it (RS-R58) |
R3a (default profile), R3b (profiles), R4p (adjudicated final) |
ProfileAdjudication (pmProfileAdjudication) |
Key (study, profile), deterministic ID; immutable **AdjudicationVersion**s (decision, must-agree supporting answers, reasons, rationale, the input vector it applied to, adjudicator, clock stamp); current pointer | Versioned (V2-18; principle 4). An adjudication whose input vector has been superseded by a DP2 correction is inapplicable to the new vector and the outcome falls back to the candidate facet until re-adjudicated (RECOVERED: the 25 September precedence rule, confirmed in screening-specialised-annotation-research.md:818-823). Superseded by the owner session (5 October 2026): this aggregate becomes the AdjudicationTask row below in the same pmProfileAdjudication collection, and after resolution the adjudication stays the current final facet, flagged InputsChanged, until explicit reconsideration (RS-R58; Q-27) |
R4p |
StudyPoolLedger (pmStudyPoolLedger) |
Append-only: study, stage, profile, filter-element version, release kind (sharedBatchOpened, personalGrant, importIntoActiveStage, stageOrFilterChange, dedupReversal, returnFromRetrieval), regime or batch plan ID, clock stamp |
Written only by the command or operation that releases the study (durable batch opening and personal grant per AP-05; D3-13e records shared-open and personal-grant separately). Never edited. Feeds amendment A's "entering screening" and PRISMA boxes 4 and 8. Legacy capture from R2a (E26) feeds the same ledger with coverage labels. Superseded by the owner session (5 October 2026), see the HistoryEvent row below: first release becomes WorkFirstReleased and stage pool membership becomes separate StagePool* events |
R3a |
HistoryEvent (pmHistoryEvent, replacing the planned pmStudyPoolLedger; envelope contract C20) |
Common versioned envelope: eventId (deterministic over event type, project and idempotency key), eventType (closed set extended only through C20), family, schemaVersion, project, Study, lineage (merge or unmerge), stage, step, activity, subjectReviewerId, actor {Member, SystemRule, AIScreeningModel, ExternalSource, Operator}, effectiveAt and recordedAt (clock stamp and UTC), cause (kind, command or operation ID, cause records), sourceVersions, before/after, ordered reasonCodes, clauseEvaluation tree, coverage, per (Study, stage) seq, optional explanationText. Types stored here: StagePoolBaselineMember, StagePoolEntered, StagePoolDeparted, WorkFirstReleased (renamed from the round-2 StudyEnteredPool, so it no longer clashes with stage pool entry; releaseKind ∈ SharedBatchOpened, PersonalBatchGrant, ExplicitAssignment, UnbatchedAvailability, InheritedThroughMerge), ReviewStarted (payload ReviewStartEligibility), and the conversion types BaselineConverted, ConversionRolledBack, ConversionQuarantined |
Inserts only, no TTL, retained while the project exists. Written in the transaction that changed the evidence, or by the stage pool sweep operation with the filter activation stamp as effectiveAt. A duplicate idempotency key is success. Every entry records its justification (filter version, clause tree, input versions, cause, actor); a departure is a screening exclusion only when that is the failing input. Re-entry opens a new episode and never a second distinct Study. Admission, selection, counts and readiness never read it. Other event types named by the specifications (for example FormVersionPublished, StudyMerged, AcceptedResultVersionCreated, ContributionExcluded, TrainingAttemptStarted) are adapters over the existing immutable record, or new types added through C20 where no record exists; the C20 freeze lists which. PROPOSAL names and storage (SP §3.5, §3.12, §3.13; OS-A07, OS-A10, OS-A11) |
R3a (pool and release types); envelope frozen at F1a |
AdjudicationTask (pmProfileAdjudication, the task aggregate; owner session) |
Key (project, study, profile, trigger, generation), deterministic; at most one open task per (Study, profile, trigger). Triggers: decision tie, unresolved Unsure, reason disagreement, sole-source AI-model Unsure. Exact input decision versions; assignee captured from the current AdjudicatorAssignmentVersion; editor claim (CAS plus lease); state Open, Claimed, Resolved, Withdrawn (with reason), Superseded. Immutable **AdjudicationVersion**s (decision, reasons and must-agree answers, rationale when the profile requires it, the input vector, the individual adjudicator, clock stamp) |
Pending adjudication is not a definite outcome. Before claim, a satisfying correction withdraws the task and a still-tied one refreshes its inputs; after claim, a changed input vector returns InputsChanged at submit and keeps the draft (RS-R58). A reconciler who cast a decision is never offered the task unless the override grant applies (RS-R17, RS-R18). Served through the system-defined adjudication step of every stage that binds the profile, reachable even when the outcome moved the Study out of the pool (RS-R59, SP-R91, SP-R92). PROPOSAL (tie and adjudicator amendments, OS-A13; Q-32) |
R4p |
| AdjudicatorAssignmentVersion (owner session) | Per profile and optionally per trigger: a project member or an eligible project group; actor and time | Versioned and audited; changing it needs no profile publication; an assignment never grants adjudication authority; with a group, the individual resolver is recorded. Storage PROPOSAL: the profile head's operational record with history in pmDefinitionSettingsAudit (RS §3.9) |
R4p |
ScreeningDiscussion (owner session, PROPOSAL name) |
Key (project, study, profile, conflict generation); participants by protected identity; the initial decision versions that revealed the conflict; exposure entries; state Open, Resolved, EndedUnresolved; closing reason |
Starts only after submitted independent decisions conflict; corrections are new decision versions; independent agreement uses the initial observations; an unresolved end applies the tie policy. Messages are permissioned audit records (D4-02, D3-25; RS-R60 to RS-R64) | R4p |
AIScreeningModelConfiguration (pmAIScreeningModelConfiguration; owner session) |
Key (project, configuration ID, seq). Immutable versions: model name, provider, model version or artifact reference, intended use, decision-label vocabulary with the mapping to Include, Exclude or Unsure, project-supplied thresholds, the training-set context (description and, where known, the frozen list of training and evaluation Studies with exact human decision versions), default run context, documentation links, and an explicit "not supplied" list | The project's own description of a model whose decisions it may import. Versions never change; profile versions, runs and decisions reference an exact version. Never a user, member, login or permission holder (RI §3.11, §3.14; C22; OS-A20) | XS1 |
ExternalScreeningRun (pmExternalScreeningRun; owner session) |
One delivery from one source: source type and policy entry, exact model configuration version (AI), source run ID and SyRF run ID, supersedesRunId, the profile version and label mapping, importer, imported-at, source timestamps, dataset provenance, file digest, row counts, per-row validation results, state Previewed, Validated, Accepting (n of N), Accepted, Rejected, Superseded |
Idempotent by source, source run ID and file digest. A validated but unaccepted run changes no outcome and no pool. Acceptance is a resumable operation with one Study-scoped transaction per Study (RI W9 to W11; C22) | XS1 |
ExternalScreeningDecision (pmExternalScreeningDecision; owner session) |
Key (project, profile, source key, study) plus a version sequence. Original label, mapped decision, confidence or score and threshold where supplied, source record identifier and how it resolved to a current Study (including the merge-lineage path), onTrainingInput and onEvaluationInput, explicit missing-metadata markers |
A source holds at most one current decision per Study and profile; reruns and corrections are new versions, never extra voters. Counts only under the profile's ScreeningSourcePolicy role (ContributingVote or SoleScreener) and scope, and only after accepted import. A model Unsure under a sole-screener policy goes to human adjudication; a human resolution never changes the imported decision (RI-R32 to RI-R44; C22) |
XS1 |
4.3 Reconciliation and accepted answers¶
| Aggregate, entity or ledger | Key and contents | Key invariants | Introduced |
|---|---|---|---|
ReconciliationTask (pmReconciliationTask) |
Key (study, form), deterministic ID (RE4). State: pinned form version seq and the pinned candidate session versions (state, not key); drift state (open, inputsChanged, held, completed); match set with pairing history; ReconciliationSession entity (authority scope reconciled, current holder, versions Save and Complete, drafts through SessionDraft keyed by the task); editor claim (holder, lease expiry, generation; the X-RECLAIM claim); ReconciliationAssignment entities (assignee, expiry for unstarted work only, started, released, reacquired, audit, ExpiryWarningIssuedAt scheduler marker); audited admin release |
One task per study × form; versions are recorded, never keyed, so a publication that makes candidates incompatible puts the task into inputsChanged and PublicationImpactPolicy decides which candidates still qualify (DD-07, Q-D2 closed by RE4). Every qualifying candidate takes part (SF4). A reconciler is never a candidate on the same study (Q-36 default; owner session: Q-36 decided, with an explicit audited override grant as the only exception, RS-R17, RS-R18). Drift never retracts gold. Target-1 forms create no task (Q-29, PROPOSAL; superseded by the owner session, 5 October 2026: a task exists for every form with at least one qualifying candidate, including target-one forms in both ReconciliationPolicy.targetOneHandling modes, RS §3.1). "Started" means the reconciliation session has a draft or an explicit version. Only the assignee can claim an assigned task; admin release revokes the editor claim through the outbox; editor-lease expiry never expires a started assignment (RT-01, RT §5.2). The editor claim works with tracking off. Owner session: expiry of unstarted assignments is optional and off by default (Q-30); identity blinding comes from the form version and candidates appear under a per-session presentation mapping (RS-R24 to RS-R30); the drift trigger "a dedup alias" becomes "a duplicate consolidation or reversal" (C21) |
R4a |
AdditionalReviewRequest (pmAdditionalReviewRequest) |
Task, requested reviewer, status (requested, returned, withdrawn, expired), returned session; a single-use scoped admission (study × form × reviewer) recorded as a requestedReview claim on Study |
Lets exactly that reviewer past pool, bucket and capacity filters (AP-03, D3-13c); provenance on the resulting session; never sets gold or changes the target (RA5); excluded from conversations until returned (Q-N9, recorded in the register). The bypass and "never changes the target" clauses are superseded by the owner session (5 October 2026), see RD §3.12: the request is a batch naming one form, one or many Studies, the number of additional reviews, optional member or group assignees, a reason and the requester; each Study item raises the effective target through a StudyTargetOverride version with basis AdditionalReviewRequest(requestId, raiseBy) and a scoped assignment, idempotently per (request, study); qualifying reviewers count once across routes; it never sets an accepted result; an assignment never grants a permission |
R4a |
StudyGold (pmStudyGold; snapshots pmGoldSnapshot) |
Key study, deterministic ID. Reconciled-scope **AnnotationHead**s and **AnnotationRevision**s (authority reconciled); immutable **GoldSnapshot**s referencing exact revisions (outcome-series gold from R4c); current pointer; pending-query flags; re-reconciliation flag on publication drift (VA-11) |
Snapshots are immutable; a new snapshot keeps unchanged references; the pointer changes by CAS. Shared-question gold has one owner, which is local because all reconciled heads of a study live here: the first task to publish owns it; a second task on an overlapping form sees it prefilled as accepted and may revise it with a new snapshot carrying provenance (D2-09, PROPOSAL; still the one open owner decision after the owner session, T-OI-01). Verified is an authority value from extract-and-verify (D4-03; superseded by the owner session, 5 October 2026: second-person checking is one-candidate human reconciliation and Verified leaves the authority set, RS-R03). Owner session: each AcceptedResultVersion publishes exactly one new snapshot; SingleAnnotator results write system-authored reconciled revisions with derivedFrom provenance so queries keep a reconciled target (RS §3.2) |
R4a; series at R4c |
AcceptedResultVersion (pmAcceptedResultVersion, or embedded in the task if the F1a storage ADR prefers; owner session) |
Key (project, study, form, seq) plus (project, command ID). authority ∈ SingleAnnotator (system rule), HumanReconciled, Adjudicated (profile-owned screening annotations resolved through an AdjudicationTask), MergeResolved; acceptanceMethod ∈ SystemRule, Individual, BulkConfirmed, MergeResolution; origin ∈ Native, MergeCarriedForward, UnmergeCarriedForward with the source version; input set and exact candidate versions with candidateCount; the form version (which pins standardTarget and ReconciliationPolicy), any StudyTargetOverride version and the effective target used; the gold snapshot it produced; the actor (rule and rule version, reconciler, or publication operation and confirming admin); blinding mode and a protected mapping reference; supersedes and a reason code |
Append-only. Derived standing, never stored: Current, InputsChanged, BelowCurrentTarget, SuspendedByTarget, NeedsReReconciliation, Superseded. A SingleAnnotator result needs effective target one, AutoAccept and exactly one qualifying candidate; two or more candidates always need a human reconciler (T-POL-03 unapproved). A new target, policy or input creates a new version only through the entitled rule or person; raising the target invents no reviewer. Bulk acceptance is optional, off by default and needs an explicit reconciler confirmation per Study (RS-R01 to RS-R23; Q-29, D4-03, Q-11; OS-A28) |
R4a (form results); R4p (Adjudicated); P2c (MergeResolved) |
Reconciliation presentation mapping (pmSessionPresentation, server-only read; owner session) |
Key (work item, reconciliation session seq). Per candidate: an opaque context-local handle, a random alias, a random display position and the protected link to the real session or decision version | Fixed for one reconciliation session; a new candidate is appended with a fresh alias; a later session draws a fresh mapping; mappings for different Studies are independent, so no alias continues across Studies (Q-30, OS-A02, OS-A03). The client receives handles, aliases and positions only | R4a; R4p for adjudication |
QueryWorkItem (pmQueryWorkItem) |
Key accepted-answer version; Concern entities (raiser, proposed correction, explanation) each with a ConcernResolution (outcome: accepted, rejected, addressedByUpdate, openForApplicabilityReview; explanation optional; resolver; audited self-review); status; child-resolution tracking; queryEditor claim |
Gold stays effective with a pending flag; per-concern outcomes; children resolved before a replacement snapshot; QY8/QY9 closure. Query review uses the same editor-claim mechanism as tasks (AC-R4b-09). "Outcome" is never used for a concern (DD-11) | R4b |
4.4 Review Workflow¶
| Aggregate | Key and contents | Key invariants | Introduced |
|---|---|---|---|
Stage (pmReviewStage; versions pmStageSettingsVersion) for canonical projects |
Key = the stage ID already embedded in Project (which keeps name, order, navigation and security grants, referenced by stage ID). Immutable **StageSettingsVersion**s: bound form and profile versions (PV2, D2-04), steps with dependency edges and AND/OR groups, compulsory, handoff and terminal scope, collective satisfaction, extra-vote admission, route policies (DP6/DP7, Q-15), VS1, BL1 and EW1 defaults with per-step overrides, the filter element (FEAT-008 filter-set schema decided at F3), the optional capacity cap (D3-17), tracking setting (D3-18), idle timeout, assignment-expiry default (RA3), and references to the allocation regime and the batch plan by ID; current settings pointer; lifecycle status (Draft, Active, Completing, Completed) and mode (automatic or manual); StageChangeRequest entities (pending, approved, declined); status history |
Versions immutable; dependency cycles rejected; Active is derived from status, never a separate switch. A Completed stage refuses settings publication except through an approved change request, re-checked at commit (RX2, LC1; flow per Q-02). Completion is two-step: Completing fence, drain, verify, Completed (DC-09); completion withdraws that stage's claim references through the outbox, a claim surviving if another bound stage still uses it (RT-18). Lifecycle mode has one owner, the lifecycle part, not the settings version (V2-17). The regime and batch-plan records stay in their own collections; embedded Project.Stage.WorkloadShares and ProgressiveBatches are legacy-only (AP-11). PROPOSAL at F3 (DD-09). Owner session (5 October 2026), see SP §3.2 to §3.11: the route policies (DP6/DP7 cross-stage part, Q-15 alternatives) are superseded by the stage study filter; BL1 moves to the form or profile; the idle timeout, the in-progress limit and target enforcement move to the form (the cap becomes a form CapacityCap); the assignment-expiry default moves to form and profile operational settings, optional and off by default. The settings version gains: the embedded StageStudyFilterVersion; the progression basis (OwnIncludeSufficient by default or CollectiveIncludeRequired, Q-01) with a tighten-only step override; per screening step the extra-screening setting (Stop default for new combined steps, Q-24) and exclusion-stop (personal and collective, both on by default, scope DependentSteps, PROPOSAL); the saved-work setting (AllowCompletion or PreserveOnly, Q-28); the started-work-after-departure setting (Allow default, placement SP-AMB-01); an optional route capacity cap, stricter than the form baseline only; the reconciled-hint hide-only step override; the browsing setting (off by default, PROPOSAL); and step kinds review, system adjudication and training (SP-R91, SP-R92). Dependencies exist only between steps inside a stage; there is no incoming stage-entry gate. Automatic completion follows remaining-work rules and reopens an automatic Completed stage as soon as remaining work appears; a manually completed stage stays Completed until an authorised reopening (Q-02) |
R2a (minimal binding), R3a (steps, filter, pool history), R3c (lifecycle) |
StageStudyFilterVersion (embedded in pmStageSettingsVersion as filter {filterVersionId, seq, root, dependencySet, digest}; owner session) |
filterVersionId deterministic over (stage, filterSeq). A tree of AND/OR groups over profile outcome clauses (in/notIn on Included, Excluded, Unresolved with optional resolution sub-states) and accepted answer clauses (option identities or typed values, accepted question versions, optional authority restriction), joined by AND to an implicit base predicate (Study Current, lifecycle Active, not hidden by withdrawal); the dependency set of profiles and questions it reads |
Immutable once published; a settings version that changes only steps keeps the filter version. Evaluation is three-valued and fails closed on Unknown. No clause reads a reviewer's own decision, another stage's pool, remaining work, capacity or allocation, so recursion cannot arise. Matching the filter means neither that review is needed nor that it happened; a filter failure is never a screening exclusion. Changes publish under the settings fence and a sweep operation records transitions (Q-15; consolidation §3; SP-R01 to SP-R12) | R3a |
| Stage pool and ReviewerStudyPool (derived; owner session) | The stage pool is the set of current Studies satisfying the current filter version, compiled into a predicate over Study and its canonical summary. The reviewer study pool is the subset allocated or assigned to that reviewer and currently available under the admission rules | Never stored; a membership cache is allowed only if every read proves it current and the F3 benchmark needs it. A Study that leaves the stage pool leaves the reviewer pool at once; started work that may continue appears as saved work outside both pools. Optional browsing shows only the reviewer pool, preserves blinding and grants nothing (OS-A27, D4-19) | R3a; browsing R3c or later per rollout |
ReviewStartEligibility (payload of a ReviewStarted HistoryEvent; owner session) |
Route (stage, settings version, step, activity, session); pool basis (filter version, compact clause evaluation, input versions, episode); step basis (dependency results, exclusion-stop evaluation, progression basis); allocation basis (regime, batch plan, grant, assignment, override or request); availability basis (capacity cap version, places, claim, or NotEnforced (tracking off); in-progress limit; capability and authorization audit reference); admission digest; actor; effective and recorded time |
Written once per session and route at first start (first autosave, first explicit Save, or the decision itself), deterministic ID with $setOnInsert, outside the Study transaction when the start is an autosave. Opening a Study without editing records nothing. It explains why a reviewer could start; pool membership alone does not (SP §3.8; OS-A08) |
R3a |
| CapacityCap and the route cap (owner session) | Form baseline Off, EffectiveTarget or EffectiveTargetPlus(n), applied through every route; a stage may set a stricter route cap per bound form |
Separate from the target (D3-17); off by default and EffectiveTarget when enabled are proposed defaults, not approved; one shared count per Study × form; lowering a cap never evicts a held place; a cap never falls below a Study's effective target (PROPOSAL). Form setting in the AnnotationForm operational record; route cap in the stage settings version. Enforcement exists only while tracking is effective (SP §3.11) |
R2b (form baseline); R3a (route cap) |
| TrainingStep (a step kind; owner session) | A step that binds exact form and/or profile versions, one TrainingReferenceVersion and one TrainingPolicyVersion |
Changing what it binds publishes a new stage settings version. It creates no live work, claims or pool events and is never a hidden prerequisite; a live step depends on it only through an explicit dependency (optional PROPOSAL, TI §12) (S4; TI §3.1; OS-A18) |
Training lane |
Placement of today's per-stage settings (PH-05, RT-12, D3-18; PROPOSAL at F3). Owner-session
amendments (5 October 2026) are marked in each row; the stage-owned placements they replace are
superseded, and the classification rule is RD §3.5:
| Existing setting | Owner under shared forms | Rule when stages bound to one form differ |
|---|---|---|
Session count target (SessionCountTarget, #3732 override) |
Form (requirement part, SF2); #3732 override legacy-only. Owner session: FormVersion.standardTarget inside the immutable form version (target-versions-form, OS-A12); per-Study history in StudyTargetOverride; no step-level override |
n/a (one form target; the effective target is the current override or the standard target) |
Target enforcement (EnforceAnnotationTarget) |
Stage route policy as an optional capacity cap (D3-17), off by default. Owner session: form-owned CapacityCap applied through every route, with an optional stricter route cap in the stage |
Most restrictive bound stage sets the cap (superseded by the owner session: one shared count; a route cap only refuses admission through that route) |
In-progress limit (MaxInProgress) |
Stage in use. Superseded by the owner session: the form owns the per-reviewer in-progress limit (D2-07, Q-28) | The stage being used sets it; a shared session counts once (superseded: one form-owned limit; a shared session still counts once) |
| Idle timeout | Stage. Superseded by the owner session: the form owns the inactivity timeout (D2-07, Q-28) | Most restrictive bound stage (superseded: one form-owned timeout; one idle tab never releases the place while another connection is active) |
| Hide excluded studies; excluded progress grouping | Stage display settings, as a sub-setting of EW1 (D3-09, eligibility D8 mapping). Owner session: the saved-work setting (AllowCompletion or PreserveOnly) and the started-work-after-departure setting govern continuation (SP §3.9) |
Per route |
Self-reconciliation (AllowSelfReconciliation, no writer today) |
Project authority policy, not the stage (Q-36). Owner session: Q-36 decided; an explicit audited override grant, a C10 capability, is the only exception | n/a |
| Search and partition filters | The filter element of the settings version; legacy PartitionSet and the study-partitions route retired (AP-20). Owner session: the StageStudyFilterVersion (filter schema v3) |
Per stage (each stage has its own pool) |
| Tracking (#3876) | Binding-scope setting (D3-16a). Owner session: project scope is a PROPOSAL (SP-AMB-12); D3-16 stays a brief item |
Tracked if any bound stage is |
| Category guidance | Stage presentation text, never evidence (A-15) | Per route |
| Blinding (BL1), VS1, EW1 | Stage, with step overrides. Superseded by the owner session: reconciliation identity blinding is owned by the form (the profile for screening reconciliation and adjudication), blinded by default; reconciled-answer hints are a form baseline (shown by default) that a step may only hide; EW1 becomes the saved-work setting | BL1 most restrictive; EW1 and VS1 per route (Q-28). Superseded: no stage blinding rule exists; hints follow the form baseline narrowed per step |
| Assignment expiry default (RA3) | Stage. Superseded by the owner session: optional, admin-configured and off by default in form (tasks) and profile (adjudication) operational settings (Q-30) | Per the stage the assignment was made through (superseded: per form or profile) |
| Allocation regime, batch plan | Their own aggregates, referenced by ID | One plan per shared form (AL1); refuse allocation on canonical stages until AL1 (D3-13a) |
4.5 Review Design¶
| Aggregate | Key and contents | Key invariants | Introduced |
|---|---|---|---|
QuestionDefinition (pmQuestionDefinition; versions pmQuestionDefinitionVersion) |
_id record GUID; unique (project, questionId) so system question IDs can repeat across projects (VB-11). Identity: parent, definitionOwner (project or profile), entity type identity (EntityTypeId, minted at F1a). Status (draft, published, retired). Immutable **QuestionDefinitionVersion**s: wording, options with option identity (VA-05), help, validators, conditions, response modes and metadata (PH-06), data type and multiplicity, "Why it changed", "What reviewers need to do differently", the compatibility relation to the prior version declared at commit (D2-02), structural digest |
Parent and owner never change (D38); a data-type or multiplicity change is an incompatible version of the same identity rather than a new identity (D2-03, PROPOSAL); compatibility is immutable once any answer pins the version (superseded by the owner session, 5 October 2026, D2-02 amended and Q-34 decided: SyRF suggests a default, the authorised publisher explicitly declares compatibility and whether option mapping applies, with actor and time; the declaration and mapping are immutable from commit; a wrong declaration is corrected by guided rollback and republication, RD §4.13); FV4 revises policy, never compatibility; QD1 (published questions are retired, never deleted; drafts may be deleted); a profile-owned question belongs to exactly one profile (DP4) |
R2a; profile-owned R3b |
SystemQuestionVersion (pmSystemQuestionVersion, system-scoped) |
Key (questionId, SystemQuestionVersion, structural digest); immutable snapshot of the code-defined question at that version and code revision (E24) |
A project pins a system version only by publishing a form version that references it (D2-06); form versions never pin live code | R2a |
AnnotationForm (pmAnnotationForm; versions pmAnnotationFormVersion) |
Key (project, formId). Head: current published seq, publication seq, policy generation. Immutable **AnnotationFormVersion**s (the requirement part): ordered question-version references including ancestors, requiredness, minimum target. Operational settings record (audited, not pinned by sessions; D2-05 PROPOSAL): compare settings, gold-completeness policy, guidance, response-collection options. Owner session (5 October 2026), see RD §3.5: the requirement part holds FormVersion.standardTarget (target-versions-form, OS-A12) and ReconciliationPolicy {targetOneHandling ∈ AutoAccept, RequireHumanReconciliation (conversion alone may set NoAcceptance, RS-R04a PROPOSAL); acceptedCompleteness; identityBlinding (Blinded default); reconciledHints (Shown default); outdatedAnswerCompletion (WarnAllowComplete default or BlockUntilAddressed)}, the last four classified inside the version as PROPOSALs; the operational record holds the inactivity timeout, the per-reviewer in-progress limit, the CapacityCap, optional unstarted-assignment expiry, bulk acceptance (off by default), comparison display and guidance |
A version in use never changes (FV1). One active issue per form (D2-11). AF2 renderability is validated at publication; canonical routes never fall back to AF1 (VB-08). A size ceiling applies until the tiered benchmarks prove larger forms safe (D2-16; E28 in pins and bytes; superseded by the owner session, 5 October 2026: D2-16 replaced, no form is excluded for size, the largest project is an acceptance case and limits are engineered and measured to fit it, RD-R33). Until R2d, two forms cannot share an answerable question (A-19). Owner session: a standard-target change creates a new form version through the publication impact process even without question changes; there is no settings-only target path | R2a |
FormVersionIssue (pmFormVersionIssue; chunks pmFormVersionIssueChunk) |
The publication operation ("publish" stays the user-facing verb). Form, issued version seq, recorded policy (per-question requireReanswer/autoUpdate/doNothing, per-category treatment, option mapping only if Q-34 approves), policy generation (FV4 revisions CAS it), phase (recorded, applying, applied, stalled), ADR-020 fields (lease, generation, cursor, chunks), the impact manifest built after commit as an audit and preview snapshot, the preview digest re-checked before phase 1, the notice fan-out intent. Owner session: the generated-version plan, the override treatment per override group when the standard target changes (RD-R16), the result treatment for target and target-one changes (RS §4.6), and the guided-correction link when it corrects an earlier declaration (RD §4.13) |
Phase 1 is O(1): fence, drain, CAS the form head, write the policy and operation records in one short transaction. Phase 2 is a predicate-driven projection rewrite (pinnedFormVersionSeq < current ∧ appliedPolicyOp < op) that repeats until it matches nothing; admission and readiness for the form pause while it runs (D2-10) and fail closed on a stale projection. Writes no evidence (D2-01; superseded by the owner session, 5 October 2026: phase 2 writes, per Study and idempotently, the generated session versions, mapped revisions, result versions and override versions that the recorded treatment calls for, each attributed to the operation and the publisher, by CAS on each session head so a newer reviewer version is never overwritten; D2-10 limits are measured and the earlier figures are proposed, not approved). Categories follow FEAT-001 breaking transitivity and FEAT-003 per-session categories (PH-18) |
R2c |
ScreeningProfile (pmScreeningProfile; versions pmScreeningProfileVersion) |
Key (project, profileId). Immutable versions: eligibility question-version references, decision rules (including Unsure/Maybe at title and abstract, D4-01; primary exclusion reason as the first failing criterion in configured order, D4-13), agreement and resolution routes (including the discussion route, D4-02), must-agree supporting answers (RX1). Operational settings (D2-05): DP5 toggle, rationale setting (Q-32), keyword lists if profile-owned (PH-28, decided at F5). PRISMA phase lives in PrismaPhaseMapping (§4.8). Owner session: ScreeningProfileVersion settings move into the immutable version: sufficiency rule, unsureEnabled (on in the title/abstract template), tiePolicy ∈ ExtraReview with extraReviewBound or Adjudication (no inferred default), handling per trigger, discussionEnabled, adjudicationRationaleRequired (off by default), reason handling (DP5, RX1, primary-reason derivation as template guidance, no question-count limit), identityBlinding (Blinded default) and the ScreeningSourcePolicy slot (C22; reserved at F5, populated only from XS1). The adjudicator assignment stays outside the version (AdjudicatorAssignmentVersion, §4.2) |
Templates are copied, never linked (DP4, SET1). Profile versions publish through ProfileVersionIssue as Q-26 decides (owner session: Q-26 decided, mismatches with existing decisions, outcomes and adjudications are detected and previewed and the admin's treatment is applied after a final recheck, RD §4.12). Re-publication that changes eligibility requires an amendment entry (D4-05, decided) |
R3a (one default compatibility profile), R3b |
ProfileVersionIssue (pmProfileVersionIssue) |
As FormVersionIssue, for profile versions and the decisions cast under earlier versions | As above; treatment per Q-26 (owner session: keep decisions pinned, request new decisions, or carry compatible decisions forward as attributable generated profile-session versions; policy recorded at profile scope, never per stage; required new screening stays pending; originals and frozen reports untouched; the ProtocolAmendment entry commits in the same publication when eligibility changes, RI W5) |
R3b |
DefinitionTemplate (pmDefinitionTemplate) |
Template ID; scope: system (CAMARADES-curated catalogue, administered by an application role) or project (copy from a project the user administers); kind (question set, profile, form, entity type per TC1, outcome schema); versions; a copy record (target project, source template and version, time) kept on the template |
A copy never changes when its template does. Project-scoped templates carry a project ID; system-scoped ones are the third exception to principle 5 (D2-15, PROPOSAL; Q-D1, PH-27). R1a records copy provenance on the template's own copy record, so R1a adds no field to Project before R0's floor (V2-16). The system scope is superseded by the owner session (5 October 2026, D2-15 amended), see the CatalogueItem row below; project-to-project copy is pending confirmation (AC ambiguity B5) |
R1a (question templates), R3b (profiles), C1 (entity types), O1 (schemas) |
CatalogueItem and CatalogueItemVersion (the system-scoped part of pmDefinitionTemplate; pmCataloguePublicationRequest; owner session) |
One application-wide CAMARADES catalogue (catalogueId = camarades, a dimension that lets future catalogues with distinct permissions be added without re-keying). Items: question set, form, profile, entity type, outcome schema; immutable versions. CataloguePublicationRequest: requester, source definition version, status, reviewer, decision, reason. Copy provenance on project copies: copiedFrom {catalogueId, itemId, versionId, copiedBy, copiedAt} on the new canonical definition records |
Administered by the catalogue administrator application role, never by project grants. Direct entry, sharing a project definition into the catalogue (a versioned copy with source, version and sharer provenance) or approval of a publication request. A new catalogue version never changes a project copy and a project edit never changes the catalogue; adopting a newer version is an explicit copy through ordinary publication. Template scientific content waits for T-SI-03 (D2-15 amended; ACD §3.4) |
R1a (questions, forms, requests), R3b (profiles), C1, O1 |
StudyTargetOverride (pmStudyTargetOverride, append-only; owner session) |
Key deterministic from (project, study, form); versions (override, seq), each with value, basis (SetByAdmin, AdditionalReviewRequest(requestId, raiseBy), MergeConfirmation(mergeId) or Removed), madeAgainst {formVersionSeq, standardTarget}, reason, actor, time and clock stamp. EffectiveTarget (derived): the current override's value unless Removed, otherwise the current form version's standardTarget; projected into Study.currentEvidence |
An immutable Study × form requirement decision applying across every route; no step-level override. Changing an override creates no form version. When a new standard target is published, every override gets an explicit admin treatment in the preview (keep the effective value, rebase or remove; the suggested default keeps each Study's effective target), so no effective target changes silently (RD-R14 to RD-R17, the treatment set is a PROPOSAL). Accepted results and readiness snapshots record the form and override versions they used. General statistics show the standard target and list study-specific exceptions separately |
R2c (overrides and the publication treatment); R4a (additional-review requests) |
DesignDraft and DesignDraftChange (pmDesignDraft, append-only pmDesignDraftChange; owner session) |
A named unpublished proposal for the next version of one form or profile, including pending question edits; several may exist per form (D2-11). Each change records (draftId, draftRevision), actor, time, the item changed, its base item revision and before and after values. DesignPresence (who views or edits) lives in hub connection state and is not stored |
A draft's working state changes only by appending a change; a stale base is refused and the local edit is kept beside the current value; changes appear in every open view; a draft never changes a published requirement or a reviewer's form and never starts an impact flow; one publication operation per form at a time, and a draft published after another rebases and recomputes its impact. Presence is never an audit record and never grants or blocks an edit (collaborative question drafts, OS-A01; RD §3.7, §4.7). Replaces the single designer pending-edit record with a lease (PH-33) | R2a (single editor), R2c (presence and live updates) |
TrainingReferenceVersion and TrainingPolicyVersion (pmTrainingReference + pmTrainingReferenceVersion, pmTrainingPolicy + pmTrainingPolicyVersion; owner session) |
Reference: (project, reference ID, seq) with practice items (project Studies) and expected answers or decisions pinned to exact form, profile and question versions, assessor notes, author and time; may be seeded by copying an accepted result or outcome, recording the source version. Policy: (project, policy ID, seq) with scoring rubric, pass criteria, assessment mode, feedback disclosure, retry rules, admission (none, automatic on pass, manual approval) with the target group, and whether promotion is allowed | Immutable once published; edits publish new versions and attempts pin the versions current when they start. Never part of StudyGold, never an AcceptedResultVersion, never a screening outcome. Numbers in pass criteria are per policy and not approved platform defaults (S4, OS-A18; TI §3.2, §3.3) |
Training lane |
OutcomeSchema (pmOutcomeSchema) |
Project-owned schema versions (series and observation fields with roles, types, validators, cardinality). Supplied schemas (legacy-compatible, event-count) are system-scoped templates copied into the project | Published versions immutable; forms pin allowed versions (OC1, C14) | O1 |
EntityType (pmEntityType) |
Project; capabilities (classifies animals, structured subsets); numbered child questions; legacy category alias; TC1 templates | Identity is minted at F1a as a shared-kernel EntityTypeId for the seven legacy categories plus cohort, outcome measure and experiment; the aggregate with capabilities and project-defined types arrives at C1 without re-identifying anything (DD-12) |
identities F1a; aggregate C1 |
SharedConcept (pmSharedConcept), ProjectRule (pmProjectRule) |
Concept definitions; versioned rules linking concepts | Defined once; paper-specific mappings are answers; rules publish under the Design capability (Q-19). Owner session (Q-18, Q-19 decided; OS-A19): ProjectRule versions are **ClassificationRuleVersion**s, (project, rule ID, seq) with kind Conjunction, Containment, Disjointness or Exhaustiveness, the concepts or option sets, the scope and an expression under a versioned grammar; append-only in pmProjectRule (TI §3.8) |
C1 |
4.6 Classification and populations¶
| Aggregate | Key and contents | Key invariants | Introduced |
|---|---|---|---|
AnimalPopulation (pmAnimalPopulation) |
Study; population with its whole-population cohort; instance membership | Every instance belongs to exactly one population. The default whole-study population needs no document: its ID is derived deterministically from the study ID and every answer carries it from the first canonical write (C2), so enabling classification never re-keys answers; the aggregate is created only when C1 enables classification for the project (DD-24) | C1 |
| Entity instances | Not an aggregate: an instance's identity is its label head's ID in the author's scope, minted once; rename is a new label revision; delete is a set of withdrawal revisions on the label head and its descendants in one commit; duplicate mints new IDs with copiedFrom provenance; population membership is an instance attribute (VB-09, versioning-model.md) |
— | R2a |
InferenceResult (pmInferenceResult, derived) |
Study and population; suggested inferred cohorts, proofs, withdrawals. Owner session: key (project, study, population, basisKind, basis ID, rule-vector digest, engine version) with basisKind ∈ CandidateSnapshot (one reviewer's own session version) or AcceptedResult (one AcceptedResultVersion); propositions with proof states, dependencies, reason codes, inferred groups, contradictions and count statements only where proven; lifecycle Current, Superseded (links its successor) or Withdrawn |
Rebuildable projection; never authoritative; never written back as a reported answer. Owner session (S5, OS-A19): a beta, off by default, explicit project-designer opt-in (an audited project setting; baseline conversion never enables it); inputs only from the current reviewer's own authorised snapshot or a pinned accepted result, never a mix of unreconciled reviewers; never a vote, accepted answer or PRISMA count; superseded and withdrawn results stay as history while the project exists (TI §3.7, §3.9) | C2 (beta) |
4.7 Identification and deduplication¶
| Aggregate, record or ledger | Key and contents | Key invariants | Introduced |
|---|---|---|---|
Publication (pmPublication, system-scoped) |
DOI and PMID unique sparse; canonical bibliographic fields with per-field provenance (source project and citation); linkedProjectIds |
Bibliographic data only, never review data (L.6). Privacy rule: reading a Publication never exposes project or citation IDs from projects the caller cannot access; another project's enrichment is visible only as values. Cross-project enrichment is a PublicationEnriched fact with a clock stamp, so as-of exports cover what another project displayed (V2-03). Created at P1 from DOI/PMID at import, or linked later by a separate link record (amendment N) |
P1 or P2 per amendment N |
Citation (immutable record on Study.citations[]) |
FEAT-011's fields; publicationId nullable until linked (amendment N). Owner session: a citation's home Study is the Study created for it at import, and it never moves; a consolidated Study links its inputs' citations by ID through StudyVersion.referenceLinks[] |
Never modified after creation; linking never rewrites a Citation. Whether Citations move to their own collection for size is decided before P1. Owner session: two imported citations are never collapsed into one fabricated original; storage stays on the home Study unless measured sizes require a change (consolidation §1; RD §3.3) | P1 |
StudyAlias (set on the primary Study) and Study.mergedInto (on each secondary) |
Alias entries: secondary study ID, merge operation ID, provenance | A merge never re-keys immutable records: nothing under the secondary study changes. Reads, candidate selection, statistics and PRISMA resolve aliases through AliasResolutionPolicy; ContributionQualificationPolicy counts a reviewer once across aliased studies; when one reviewer reviewed both, the resolution chooses the current session and supersedes the other with provenance. Merge and split are ADR-020 operations writing both Study documents and refusing busy studies (claims, drafts or open tasks). Split removes the alias and re-derives. FEAT-012's "canonical Study" is "primary Study" (amendment L). Presentation: D2-12 (DD-08, V2-02). Superseded by the owner session (5 October 2026; D2-12 replaced; OS-A29), see the rows below and C21: two active Studies linked by an alias are replaced by one consolidated current Study; busy Studies are not refused, active work is warned about and rechecked at commit; split is replaced by unmerge |
P2 |
Study parent state and tombstone (fields on pmStudy; owner session) |
state ∈ Current, Tombstoned; currentVersionId; tombstone {reason (ConsolidatedByMerge or ReversedByUnmerge), operationId, at, actor, successorStudyIds}; consolidatedInto on a merged input for redirects. A missing state reads as Current |
Changed only by merge or unmerge activation, by CAS on Audit.Version. Only Current Studies are allocated, listed, offered or counted in current totals; a tombstoned Study refuses every write (StudyConsolidated with a redirect, draft kept) and stays readable in history, as-of exports and audit. The R0 floor step before P2 adds the tombstone predicate to the shared pool, capacity and list fragments, so legacy readers also exclude it (DM §3.1; DM-R20) |
P2a |
StudyVersion (pmStudyVersion, append-only; owner session) |
(study, seq) with a GUID. Displayed bibliographic fields, each {value, origin, decidedBy, decidedAt, confirmation} with origin ∈ InheritedFromReference(citationId), SelectedFromReference(citationId), ManualOverride, SystemRule(ruleId, ruleVersion); referenceLinks[] {citationId, homeStudyId, linkedBy, linkedAt, reason, sourceDocumentKey?}; sourceDocumentLinks[] {documentRef, kind, linkedBy, linkedAt, sourceStudyId} (the prepared multi-source link, D4-08) |
Never changes; a bibliographic edit, a merge and an unmerge each append a version. With one reference and no override the Study shows that reference's values transparently; selected values and manual overrides take precedence; references never change; a FEAT-011 Publication value never changes Study fields silently. A P1 import writes version 1; a Study created before P1 gets version 1 on first need, labelled CurrentSnapshotOnly (RD §3.2; DM §3.2; DM-R17) |
P1 (new imports); P2a (merges); first need or conversion (existing Studies) |
StudyMerge (pmStudyMerge, items pmStudyMergeItem; owner session) |
One duplicate consolidation with its manifest: inputs[] {studyId, studyVersionId, evidenceWatermark, evidenceDigest}, the reserved consolidated Study ID, status (Draft, AwaitingResolution, ReadyToCommit, Staging, Committed, Abandoned, Failed), entry point (queue item with ASySD version, reviewer flag or library selection), conflict counts, target confirmations, the draft consolidated StudyVersion, attribute decisions, the active-work digest, initiator, committer and times; items list every evidence item with exact source versions, treatment (CarryForward, Resolved(conflictTaskId), NotCarried(reason)) and resulting record IDs |
Header changes by CAS until Committed, then never. A unique partial index keeps a Study in at most one active merge. Staging writes the consolidated records under the reserved ID (invisible until activation); activation is one transaction that validates every input's current version and evidence watermark, inserts the consolidated Study, tombstones the inputs, freezes the manifest and writes the events and durable intents. A failure leaves the originals current. Merge-created records cite exact source versions, the merge, the choices, the actor and the time (DM §3.3, §4.5; DM-R01 to DM-R13; C21) |
P2a (unreviewed), P2b (reviewed), P2c (results and adjudications) |
MergeConflictTask (pmMergeConflictTask; owner session) |
One conflict that must be resolved before commit: kind (same-reviewer form sessions, same-reviewer screening decisions, conflicting accepted results, conflicting adjudicated outcomes, differing reviewer targets, differing bibliographic fields or attributes), exact input versions, assignee (merging user, original reviewer, reconciler, eligible adjudicator or group), status (Open, Delegated, Resolved, Stale, Withdrawn), working state through draft mechanics, resolution, resolver and time, delegation record |
Resolution precedes commit; a changed input makes the task Stale and returns it to its assignee. The merging user chooses among the inputs' values or leaves an answer unanswered and never types a new value into a reviewer's session (PROPOSAL); delegation sends a task naming the merge and exact inputs to the original reviewer; the actual resolver is recorded and an admin's choice is never shown as the reviewer's; Complete still passes validation. Not a reconciliation task (DM §3.4; DM-R05 to DM-R07, DM-R22) |
P2b, P2c |
StudyUnmerge (pmStudyUnmerge; owner session) |
References the merge and the consolidated Study; the consolidated StudyVersion and evidence watermark at preview; the restored Studies with their new StudyVersion (reason Unmerge); items[] for every post-merge item {kind, source record and version, lineageSuggestion, choice (CarryTo(studyId) or LeaveOnHistorical), warnings, resultingRecordIds}; status, actor and times |
A new immutable action: it tombstones the consolidated Study (ReversedByUnmerge), returns each input to Current and never erases the merge. Each post-merge item needs an explicit choice; "both" is refused; moved items become UnmergeCarriedForward records with provenance. Accepted results whose inputs change are warned about, kept, and replaced only by explicit action. A chain is reversed from the latest merge first (DM §3.7, §4.9, §4.10; DM-R14 to DM-R16, DM-R23) |
P2a onwards |
CurrentEvidenceView (Study.currentEvidence, top-level sub-document on pmStudy; owner session) |
Per form: effective target and its source; each session's reviewer, session ID, current version, status, standing and origin (own, carried with source version, or merge-resolved); the current accepted result with authority, origin and an "inputs changed" flag. Per profile: current decisions and outcome. Lineage: consolidatedFrom and the merge, or restoredBy and the unmerge |
A stored projection, not authoritative and rebuildable. Written in the same transaction as every canonical command that changes current evidence (CR-1) and by merge and unmerge activations. It takes over the per-form member list of CanonicalSummary; the legacy-shaped per-stage projection stays in the summary until R7. Size, write cost, rebuild parity and list-read cost are proved before its design freezes (owner requirement; DM §3.6; DM-R13) |
P2a (shell); R2a onwards for ordinary commands per the storage ADR |
DuplicateReviewItem (pmDuplicateReviewItem) |
FEAT-012's review queue item: the pair, scores, review summaries, decision. Owner session: decision outcomes Confirm duplicate (starts a StudyMerge), Not a duplicate, Distinct report (related reports such as an abstract and an article; no merge; grouping deferred, D4-08) and Defer |
Studies with review data are never merged automatically (amendment D). Owner session: "Not a duplicate" and "Distinct report" are never re-queued for the same pair and algorithm version; automatic consolidation runs only where neither input has any explicit version, decision, accepted result, draft or claim (drafts PROPOSAL); QC samples and reviewer flags are entry points (Q-37; DM §3.9, §4.13) |
P2 |
DedupAuditLedger (pmDedupAuditLedger) |
Every dedup decision with confidence, source, actor, time, reversibility | FEAT-012 §10.2 offers embedding or a separate pmDedupAuditLog; this plan takes the separate collection under the ledger convention, recorded in amendment L |
P2 |
Dedup batch staging (pmDedupBatch) |
FEAT-012 §5's staging document with a 7-day TTL | Kept as specified: transient staging that holds no evidence, so the no-TTL rule for canonical collections does not apply (V2-17) | P2 |
ExternalStepLedger (pmExternalStepLedger) |
Project, optional search or source; step type, PRISMA fields, count, timing, tool, evidence, author; supersedes | Append-only; a correction supersedes and keeps history (amendment K); box 1 from previous-review counts only if D4-11 approves | P1 |
StudyLifecycleLedger (pmStudyLifecycleLedger) |
Append-only lifecycle and retrieval events: Sought, Retrieved, NotRetrieved with reasons (amendment M, D4-07; a PDF attachment only suggests Retrieved), lifecycle transitions, PublicationLinked, accepted bibliographic corrections (NS-08), SearchWithdrawn |
Never edited; feeds as-of PRISMA counts; Study.lifecycleStatus and retrieval status are the current projection. Owner session: D4-07 decided (attributable Sought, Retrieved, NotRetrieved actions; a PDF only raises a suggestion); SearchReinstated joins SearchWithdrawn (RI §3.5, §3.8) |
P1 |
| Report-to-study link (amendment O, if D4-08) | A ReportLink record on Study (report identity, linked at, by) |
Linking never merges extraction. Superseded by the owner session (5 October 2026; D4-08 carry-forward), see StudyVersion above: prepared multi-source links live in StudyVersion.referenceLinks[] (with an optional sourceDocumentKey and its basis) and sourceDocumentLinks[]; the workflow for grouping distinct reports into one investigation is deferred (RI-R03) |
F-P decision |
4.8 Reporting and history¶
| Aggregate | Key and contents | Key invariants | Introduced |
|---|---|---|---|
PrismaPhaseMapping (pmPrismaPhaseMapping) |
Project; versions mapping each profile to a PRISMA phase (title and abstract, full text, not reported) | Project-level because it defines the set of required profiles; the profile editor is only its UI (DD-20). StudyLifecyclePolicy reads it |
R3b |
PrismaFlowSnapshot (pmPrismaFlowSnapshot) |
Frozen report with manifest (computed and reported parts, definitions, versions, coverage, digests). Owner session: inputs add accepted ExternalScreeningDecisions, HistoryEvent pool and review-start records, WorkFirstReleased entries, Study and merge lineage, search documentation versions and the protocol record version; coverage adds report identity coverage, pool-tracking coverage, the machine-assisted share per phase and legacy-gap labels (RI §3.2) |
Frozen; amendments append; never from FEAT-024 rows (MS-11). Owner session: actual review through a stage is the reporting priority and pool history is separate audit data; the exact box mapping is specialist input T-SI-05; a filter departure is never reported as a screening exclusion (RI-R04 to RI-R09) |
R5b |
ExportManifest (pmExportManifest) |
Export basis, watermark (clock stamp and bounds), definitions, versions, content digests, per-dataset coverage, erasure record (D2-14; owner session: conditional on T-POL-02, because no identity-erasure process is decided) |
Append-only; two exports at one watermark are identical (a checksum comparison). Whether manifests are stored or regenerated is the C11 ADR's choice; this page assumes stored (PROPOSAL). Owner session: manifests carry conversion provenance, the history-discontinuity record, AI model configuration and run versions, and contribution exclusions in force |
R2a (version exports), R5a |
AgreementResult (pmAgreementResult, derived) |
Per form and study set: the approved method's figures, independent and informed split, denominators. Owner session: source classes human independent, human informed, external human and machine, each shown separately; adopted hints and outputs on a model's training inputs are excluded from independent observations | Own rebuildable store, outside FEAT-024 (D3-11, brief item with a source watermark and measured budget). Formulas wait for T-SI-02 (Q-16, D4-12) |
R5c; machine class with XS1 |
ProtocolRegistration (one per project; owner session PROPOSAL name) |
Registry, registration ID, URL and date, protocol document link and version; append-only ProtocolAmendment entries (date, what changed, reason, the profile, form or filter version it corresponds to, actor, time) |
Publishing a screening-profile version that changes eligibility requires an amendment entry in the same publication; SyRF suggests "eligibility changed" and the publisher confirms or overrides with a reason (D4-05 decided; RI §3.7) | Before or with R3b |
4.9 Platform and coexistence¶
| Aggregate or record | Key and contents | Key invariants | Introduced |
|---|---|---|---|
CanonicalEnrolment (pmCanonicalEnrolment; was ProjectAdmission) |
Project; admitted scope kinds (annotation forms, screening profiles, notifications per NS-04 and D3-21, AF2 per-project admission routed through P7 targeting keyed to enrolment, PH-14); the rule that applied (creator opt-in, environment); audit | Changing enrolment never changes ownership. The single per-project enrolment mechanism for pilots, the setup wizard and flag targeting | R0 |
CanonicalOwnership (pmCanonicalOwnership) and the CanonicalScopes marker |
Registry per (project, scope) with the owner, cutover operation and operator; the marker is a set of scope references on Study and Project | The registry is audited; a reconciliation check compares it with the markers. Legacy writers include CanonicalScopes in the write filter they already use (filter miss = refusal, no extra read, no transaction needed; DD-13); direct writers go through the composite IAggregateWriteGuard; project-wide pre-checks mirror ThrowIfBulkUpdateInProgressAsync. Cutover uses ADR-020's lock, verify, stamp, release protocol; AC-R6-05 is all-or-nothing via locks (VB-07). Owner session: the registry entry gains firstCanonicalWriteAt and firstCanonicalCommandId, set by the first canonical command that writes new evidence or configuration in a converted scope, by CAS in its own transaction; the routing-rollback command requires them to be null under the same CAS, which makes the recovery boundary exact (BC §3.3, §4.8) |
R0; first-write fields with R6 |
| Command ledger record | Not a collection of its own: each canonical command's immutable output record (FormSessionVersion, decision revision batch, FormVersionIssue, GoldSnapshot, adjudication version, operation record) carries a unique (ProjectId, CommandId), the request digest and the result IDs (consistency-model §5) | Retries read it first; a different digest under the same ID is a typed 409; an indeterminate commit returns "outcome unknown". Commands without an immutable output (claim acquisition and release, draft writes) are idempotent by construction (natural key; duplicate write sequence = success). Inbox SourceIds derive from the CommandId. Retention ≥ the client retry horizon (proposal 7 days) | R2a |
Operation records (pmCanonicalOperation; chunks pmCanonicalOperationChunk) |
ADR-020-shaped records: kind (issue phase 2, projection rewrite, adoption cutover, merge, split, stage completion drain, outcome sweep), lease, generation, phase, cursor, counts, manifest reference. Owner session kinds: issue phase 2 generating versions, merge staging and unmerge staging (split superseded), stage pool history sweep (SweepStagePoolHistory) and filter-input preparation, baselineConversion, contributionExclusion, projectDeletion, projectRestoration, external screening run acceptance, bulk additional-review requests, bulk acceptance, training promotion |
One active per scope through a unique partial index. One record family with a kind field, or one collection per kind: the F1a storage ADR decides (PROPOSAL: one family). See consistency-model §7 |
R2c onwards |
LegacyWriteLedger (pmLegacyWriteLedger; was HistoryCapture) |
Append-only capture of legacy-path writes in admitted projects: screening from R2a, pool entry from R3a, retrieval and lifecycle from P1 (E26). Owner session: "pool entry" capture means first release (WorkFirstReleased); stage pool membership for a legacy stage starts at conversion with StagePoolBaselineMember events and earlier history labelled NotRecordedInLegacy |
Captured in the same transaction where the writer is transactional, otherwise into a bounded Study-embedded log moved out by a worker (VB-14); every legacy screening writer named in AC-R2a-17 | R2a |
LegacyIdAlias (pmLegacyIdAlias) |
Legacy session and annotation IDs mapped to canonical IDs at adoption | Used by #3944/#3945 remapping and exports (VB-13). Owner session: used by every baseline conversion, so no saved link breaks (AC-R6-11) | R6 |
Baseline conversion records (owner session, PROPOSAL names and storage; R4, OS-A14, OS-A15) |
ConversionInventory (pmConversionInventory, read-only survey per run, including the Q-35 premise count and the largest form's size); ConversionManifest (pmConversionManifest with chunked items: target identity of every legacy record, the legacy activity mapping per stage, target, capacity, timeout and blinding values, resolutions, dispositions, adoption findings, approver); ConversionWave (pmConversionWave); ConversionParityReport (pmConversionParityReport); ConversionQuarantine (pmConversionQuarantine); RecoveryManifest (pmRecoveryManifest, D2-13); the retirement readiness record (a decision-register document and tracker row, not a database record) |
Faithful baseline only: conversion keeps project-specific behaviour, adds no workflow constraint and never fabricates versions, reviews, votes or reconciliation results; genuinely missing history carries a legacy-gap state (§7.2). Drafts of a manifest are editable with base checks; approved versions are immutable and invalidated by any later change to the source. A failed or rolled-back attempt is never deleted. Routing rollback is possible only before the first canonical write; afterwards recovery is forward or containment, never a flattening into legacy. No migration execution is authorised (BC §3.2 to §3.4) | R6 (universal waves after pilots); R7 retirement milestone |
4.10 Notifications (programme-owned; listed for the model)¶
| Record | Change this programme needs | Owner |
|---|---|---|
| InboxNotification | Additive generic Source sub-document (type, IDs, stage list, task ID); server-provided label, context lines, typed availability and workflow state; row ID = SHA-256(SourceId, recipient); ResolvedAtUtc if D3-23 is approved; kinds registered through the kind registry (NS-03, NS-12). Owner session: D3-23 is a brief item; ResolvedAtUtc plus resolution {reason, sourceTransition, resolvedByRef} (reasons decided, completed, withdrawn, expired, superseded; resolvedByRef shaped by disclosure on read); the unread count is "unread and unresolved"; new kinds for generated versions, target changes, merge conflicts and delegation, contribution exclusion, project deletion and restoration, adjudication assignment and external runs (capture only; delivery is not authorised) |
Notification programme |
NotificationFanOut (pmNotificationFanOut) |
Durable intent written in the source transaction (occurrence, selector: a frozen recipient list or a capability evaluated at expansion, progress, lease); a leased idempotent expander writes rows in batches. C19 class (b) for notifications; "no outbox" becomes "no second notification store; durable intents are part of C15; in-memory outboxes stay forbidden" (NS-01) | Notification programme; L2 consumes |
| NotificationEmailPreferences, NotificationEmailDelivery (ledger), NotificationEmailDigest, ImportNotificationAdmission | Tolerant preferences (unknown keys kept, missing = off), kind-to-category map, delivery halt, retention (E32). Owner session: preferences gain a set of muted project IDs with the time each was muted; a muted project sends no immediate or digest email to that person while inbox rows, the badge and My work counts stay (D3-24, D3-07) | Notification programme |
NotificationContentPolicy (pmNotificationContentPolicy; owner session PROPOSAL storage) |
(project, version), immutable versions with actor and time and one current pointer. Content classes: project name (on), Study title and short bibliographic context (on), actor reference (role or context-local alias; names only where the recipient may see identities and blinding does not apply), answer values (off), free text (off), link (always). Read by both email processors after the C15 resolver and disclosure policy and checked at send time; it can only narrow what disclosure already allows; a recipient may choose minimal emails and can never widen the project policy; blinding stays owned by the form and profile; sent email cannot be recalled (O2, D3-22, OS-A26; ACD §3.5) | Notification programme |
| StudyConversation | One-to-one threads; completed sessions only; an exposure record looked up by session (feeds ExposureLedger's questionedInReconciliation); read-only context link; refuses canonical scopes through the ownership record until R4a; bound to ReconciliationTask identity at R4a; an audit record kept while the project exists (D3-25). Ownership moves to L6 at R4a (NS-19). Owner session: D3-25 decided; retained while the project is in the reversible deleted state, with no TTL; export needs an audit or export capability; text never enters candidate-answer exports or agreement statistics |
Notification programme, then L6 |
| StudyIssue, CheckedPdfProposal | Study-attention features, not notifications: issues move to Study Management, checked PDFs to the PDF programme (NS-19); recipients by capability (NS-20); issues never carry answer disputes after R4b (NS-24); their Study writers are inventoried (NS-08) | Study Management; PDF programme |
4.11 Claims (claim contract v2, frozen at F1a)¶
| Element | Content |
|---|---|
| Claim value object | {kind, scopeId, routeStage, routeStep, reservedAt, allocationRegimeId, leaseExpiry, holders}; kind ∈ {formSlot, profileSlot, requestedReview, taskEditor, queryEditor}; unique per (study, kind, scope, reviewer); keyed by form or profile identity, never by version; released when the last page using it ends (two stage tabs reuse one claim); an absolute lease expiry that guards treat as free once passed, or a bounded backstop sweep behind its own flag (RT-24) |
Capacity claims (formSlot, profileSlot, requestedReview) |
Live on Study (Study.Claims, beside legacy SlotReservations, which stay for legacy scopes) so the atomic capacity guard keeps working; written and released inside the canonical transaction (first explicit Save or Complete releases the slot claim and replaces presence exactly once); released on completion, revocation and target reduction through the outbox (RT-18 to RT-20) |
Editor claims (taskEditor, queryEditor) |
Live on their own aggregates (ReconciliationTask, QueryWorkItem): CAS plus lease; atomic "Start reconciling"; work with tracking off (X-RECLAIM) |
| Which sessions hold a place | A draft-backed claim while the reviewer is active under today's idle and disconnect timers counting draft activity (D2-07, recommended); saved incomplete; completed; Needs updating. Withdrawal frees the place. The optional capacity cap is separate from the form's minimum target and never limits requested extra reviews (D3-17). No place is held on a dependent form while still screening; the claim is taken at Include (D3-19). Owner session (D2-07, D2-08 decided; Q-28): one place per reviewer per Study × form across every tab, device and stage route; the form-owned inactivity timeout releases it only when every connection is idle beyond it or closed, and keeps the draft; the in-progress limit is form-owned and counts sessions, never connections; the CapacityCap is form-owned with optional stricter route caps, never falls below the effective target (PROPOSAL) and never evicts a held place; additional-review requests raise the effective target, so the requested reviewer has a place under the cap; own Unsure tries the dependent claim as own Include does (RS-R47 PROPOSAL) |
| Disclosure | Presence is a disclosure channel (C10): non-holders see counts and their own claim; names need the Monitor capability; never across BL1 (D3-20). Owner session: "never across BL1" reads "never across the form's or profile's reconciliation blinding" (D3-20 is a brief item under T-SP-00) |
| Production route | Claims and capacity guards exist today only when activeReviewerTrackingEnabled is effective, which is off in every deployed environment; the production route is D3-16 (recommended: #3876 as a binding-scope setting enabled per enrolled pilot); X-CLAIMS is jointly owned by the presence and FEAT-024 owners |
4.12 Training (new context, owner session)¶
Added by the owner session (S4 expansion, OS-A18). Training is requested for delivery; reserving an admission hook while deferring the rest is not enough without a separate owner scope agreement. The step kind is in §4.4 and the reference and policy versions are in §4.5. Detail: TI.
| Aggregate, entity or record | Key and contents | Key invariants | Introduced |
|---|---|---|---|
TrainingAttempt (pmTrainingAttempt) |
Key (project, training step, reviewer, attempt number), deterministic. Pinned reference, policy, form and profile versions; one training session per practice item under author scope training(attemptId) (PROPOSAL extension of AuthorScope), reusing drafts, Save checkpoints, validation and the AF2 renderer; state InProgress, Submitted, AwaitingManualAssessment, Passed, Failed, Abandoned; current assessment pointer; admission outcome (Admitted, AlreadyMember, AwaitingApproval, ConvertedToManual, Refused, or none) |
Never a candidate session; never qualifies, holds a capacity place, writes a pool event, counts toward a target, becomes an accepted result or appears in live statistics or PRISMA. State changes are append-only; submitted training sessions are immutable. Retries follow the pinned policy. Training sessions keyed by attempt and item never collide with the reviewer's live FormSession for the same Study (TI §3.4; TI-R04) |
Training lane |
TrainingAssessment (embedded in pmTrainingAttempt or pmTrainingAssessment) |
Key (attempt, seq). Kind Automatic or Manual; per-item scores and judgements; overall score; decision Pass, Fail or Partial; feedback; rubric and reference versions; assessor or system rule; time |
Append-only; a new assessment never overwrites an earlier one; the attempt's pointer moves to the effective one under the policy; a manual decision may override the automatic result where the policy allows (default yes, PROPOSAL) |
Training lane |
| Admission and promotion records | Admission uses the existing group membership contracts (R1c) with an authorizationAudit entry carrying the attempt, effective assessment, policy version and actor; promotion is an explicit operation (pmCanonicalOperation) that creates new live candidate versions or decisions, each revision carrying promotedFrom (attempt, item, assessment) |
Admission into a permitted reviewing group only, with the admission anti-escalation check; no hidden privilege expansion. Promoted evidence counts only from promotion onwards; the training records never change (TI §3.6) | Training lane (automatic admission and promotion as later increments) |
4.13 Membership, access and deletion (owner session)¶
Added by the owner session (O1 with its amendments, D2-14, D4-20; OS-A24, OS-A25). Detail: ACD.
| Aggregate, entity or record | Key and contents | Key invariants | Introduced |
|---|---|---|---|
ContributionExclusion (pmContributionExclusion, append-only) and ContributionExclusionLift |
Key (project, exclusion ID): the member, the scope (form, screening profile, stage or project), reason, actor, effective time and the confirmed impact preview digest. A lift references the exclusion with its own reason, actor, time and preview (PROPOSAL; AC ambiguity B2) |
An admin's explicit decision; reviewers cannot withdraw submitted contributions by leaving or deactivating, and membership disable alone keeps contributions valid. Excluded contributions stop counting toward qualification, effective-target sufficiency, reconciliation candidate sets, the candidate facet of outcomes, current progress and agreement statistics; current exports omit them by default. Stage scope uses recorded route provenance, never "the stage owns the session". Every version, attribution and exposure stays; dependent results stay current, flagged, until explicit reconsideration. Covers contributions recorded before its effective time (PROPOSAL). ContributionQualificationPolicy reads active exclusions directly; an operation sweeps Study summaries (ACD §3.2) |
R2a (form), R3a (stage), R3b (profile), then project |
Project.deletionState, ProjectDeletionRecord and ProjectRestorationRecord (pmProjectDeletionLedger) |
deletionState ∈ Active, Deleting, Deleted, Restoring (a top-level Project field under the N-1 rule); append-only deletion and restoration records (actor, time, reason, preview digest, operation ID); a deletion marker on every Study of the project |
Ordinary deletion is reversible: hidden from normal lists, review, editing and allocation refused with the draft kept, no notice capture, reservations and claims released, drafts, evidence, history, conversations and statistics retained. Restoration through a restricted Deleted projects view rechecks capacity and eligibility and never resurrects stale reservations. The composite write guard checks the marker beside the bulk-lock and ownership guards. Retention is indefinite until a permanent-erasure policy is approved (T-POL-01) |
X-DEL programme, amended; canonical parts with R2a and R3a; before universal conversion waves |
| Self-reconciliation override grant | A C10 capability (working name "Reconcile own contributions (override)") granted to a named member or group for named forms or profiles | Never implied by ownership, administration or Reconcile; every use is recorded on the result and shown in provenance, exports and the methods summary (Q-36; RS §3.11) | R4a |
5. Changes to existing aggregates¶
| Aggregate | Change | Release |
|---|---|---|
| Project | Explicitly the root of Membership and Permissions, conformist to #3335 membership schema 1 (its WP-M2 renames Registrations to Memberships and CustomProjectRoles to CustomProjectGroups inside the document, per the authorization handover plan cited by DD-16; UNVERIFIED here). For canonical projects, questions live in QuestionDefinition and canonical stage settings and lifecycle in the Stage aggregate; the embedded Stage entity keeps identity, name, order, navigation and security grants (referenced by stage ID). Gains the CanonicalScopes marker (R0), custom-group management (R1c), the delegation envelope (R1d) and the owner-reserved refusals (#3964). SystemQuestionVersion stays as the legacy marker. The four embedded job records stay embedded; their extraction is an explicit non-goal before R7 (A-30); the contention they cause is measured by the AC-M0-02 Project-contention line (a grant change racing a bulk job). Every new field follows the N-1 and capture rule. Owner session: gains deletionState (§4.13) and the inference beta setting in its audited operational settings (§4.6) |
R0, R1c, R1d, R2a, R3a |
| Study | CanonicalSummary sub-document (coexistence adapter, retired at R7): per bound stage, the tallies; per form and per reviewer, the membership facts ({state: placeHeld, savedIncomplete, completed or withdrawn; standing: qualifying, needsUpdating, pinnedOlderCounted, pinnedOlderNotCounted or notApplicable; versionSeq; claimActivities; admittingRegimeId; routeStageId}, as in consistency model §3.3; draft_only is never written to Study, it is read from pmFormSession and pmSessionDraft, and appears on Study only as placeHeld when a Study-writing command recorded it); per profile, the current ScreeningOutcomeSummary (this is FEAT-011's screeningOutcomes[], one array); readiness flags; the DefinitionVersionVector it was evaluated under. Not the legacy computed fields: SessionTallies and InclusionInfo are getters recomputed on every whole-Study save (StudyRepository.cs:3176-3227, ExtractionInfo.cs:31-80, per the brief; UNVERIFIED here), so R0's floor makes those getters and the claim pipeline merge the summary, and the pool, capacity and readiness predicates read it through IReviewMembershipFacts. Older binaries preserve it through [BsonExtraElements]; the F1a storage ADR chooses between this shape and VB's legacy-shaped stub sessions with evidence, default this shape. Also: CanonicalScopes marker (R0); Claims v2 (R2a, R2b); mergedInto and aliases (P2; superseded by the owner session, 5 October 2026: state, currentVersionId, tombstone and consolidatedInto, §4.7); FEAT-011 fields citations[], publicationId, lifecycleStatus, duplicateGroupId, metaAnalysisIncluded (P1, P2, R5b), with fullTextStatus replaced by the retrieval status derived from StudyLifecycleLedger (amendment M); report links if D4-08 (superseded: prepared links live on StudyVersion). FEAT-024 PendingStatistics rows continue through the FEAT-024 source-write seam (MS-06). Every canonical commit bumps the version and conflicts correctly with bulk-update locks. New pmStudy indexes (summary, markers, claims) are built through the operator route with commit quorum, preferring partial indexes (VB-18). Owner session additions: currentEvidence (the CurrentEvidenceView, which takes over the per-form member list; P2a shell, written by every command that changes current evidence); in the canonical summary filterInputs[] (current accepted answers for questions any current filter reads, with result version, authority and stamp) and stagePoolTracking[] (per tracked stage: stageId, filterVersionId, member, episodeSeq, lastEventSeq, lastEvaluatedStamp, inputDigest; read only to detect transitions exactly once, never by admission, selection or counts); per-reviewer standing excluded for contribution exclusion; the project deletion marker; the existing top-level bibliographic fields stay as the projection of the current StudyVersion so legacy readers keep working |
R0, R2a, R2b, R3a, P1, P2, R5b |
| SystematicSearch | sourceType and sourceName (P1); withdrawal state (amendment J, D3-12); referenced by ExternalStepLedger (amendment K); search documentation fields (database, date searched, strategy, limits) if D4-05 approves; schema version already lives in extra elements (SystematicSearch.cs:118-137), so new fields follow the same route. Owner session: D4-05 decided; an append-only documentationVersions[] list (SearchDocumentationVersion, PROPOSAL name: source, platform, date searched, strategy, limits, date range, searchRound, updateOf, actor, time) with a current pointer that snapshots pin; reinstatement appends SearchReinstated (RI §3.5, §3.6) |
P1, F-P |
| Investigator | No new fields. Canonical records store only opaque investigator GUIDs; account deletion anonymises the Investigator record and answers stay attributed to the anonymised identity (D2-14, VB-19); a schema check enforces the storage rule (E32). The anonymisation clause is superseded by the owner session (5 October 2026, D2-14 amended): account deletion disables access, named attribution is retained (shown with an "(account deleted)" suffix to viewers who may see identities, PROPOSAL), opaque GUIDs stay in canonical records, and identity erasure is not decided (T-POL-02) |
F1a design |
| ReviewerPresence | FormSessionId (additive; AnnotationSessionId kept); current presence keyed by form or profile for shared sessions, with the index migrated create, read both, drop; snapshots shaped by DisclosurePolicy; retention rule in E32 (RT-14, RT-21) |
R2a (link), R2b (key) |
| ReviewSessionConnection | Stable client tab ID (sessionStorage), REST heartbeat lease for drafts (the bulk-PDF lease pattern) or the hub heartbeat when available; form or scope key beside StageId; HasStartedAnnotating means the draft-changes flag (RT-10). Owner session (D2-08 decided): one record per tab or device with the session it serves, the route it came through and its last activity; connections are tracked separately while one shared session and place serve them all; the draft lease is superseded by per-answer base checks (§4.1) |
R2a |
NotificationEmailPreferences (CODE-PR; owner session) |
Muted project IDs with mute times (§4.10) | Notification programme |
| CanonicalOwnership (owner session) | firstCanonicalWriteAt and firstCanonicalCommandId (§4.9) |
R6 |
| StageAllocationRegime | Referenced by ID from StageSettingsVersion; refused on canonical stages until AL1 (D3-13a); regime schema v2 (form binding, target source) with its floor one release ahead (AP-10); one plan per shared form with equality checks (AL1) |
R2a (refusal), AL1 |
| ProjectStatistics | Families and scope kinds for form-version, question-version and profile-version usage and canonical contributions, by FEAT-024 technical-plan amendment at F2/F5 (MS-02); target-aware classification lands before R2b/R3a (MS-07); one protocol bump after gate (b), intents only until then (MS-15); OperationId = canonical CommandId | R2a, R2c, R3a, F5 |
| DataExportJob | Previous-version and as-of modes; manifest reference; export disclosure contract; only the requester or an admin may download (#3335 D11, PH-25) | R2a, R5a |
StudyConversation (CODE-PR) |
See §4.10 | #3965, R2a (refusal), R4a (binding) |
InboxNotification (CODE-PR) |
See §4.10 | Per kind |
Legacy embedded types (Annotation, AnnotationSession, OutcomeData, Screening, SlotReservation v0/v1, SessionTally) |
Frozen for canonical scopes by the marker and guard; class maps capture extra elements (never ignore only; no new fields inside computed collections); read through LegacyReviewDataAdapter; retired in R7 |
R0, R6, R7 |
6. Domain events and commands¶
6.1 Hosting rule¶
- Domain policies and aggregates live in
SyRF.ProjectManagement.Core, one namespace per context (Core/Model/<Context>/,Core/Services/<Context>/), following ADR-009's domain-service criteria (docs/decisions/ADR-009-domain-vs-application-service-classification.md:24-58,CODE-MAIN). - Command handlers (application services) live in
SyRF.ProjectManagement.Application, which today holds one service,ReviewStatsQueryService(CODE-MAIN, directory listing). Every canonical command has exactly one handler there. - API and PM are hosts that invoke the same handler: interactive commands over HTTP in the API;
operations, sweeps and time-driven transitions through a
PM.Messagesconsumer in PM. Quartz schedules only; a scheduled notice is a command to PM that marks the aggregate and captures inline. - PM gets notification-capture capability (the notification flags, or the admission-record pattern) as an R0 item (E59), because operations hosted in PM capture notices (NS-01).
- Today's engine is API-hosted:
SubmitAnnotationSessionService.cs(673 lines) andReviewController.cs(1,707 lines) undersrc/services/api/SyRF.API.Endpoint/(CODE-MAIN, line counts), calling Core domain services.docs/architecture/platform-architecture.md:125, :134, :139says the API is "intentionally thin" and PM holds "all business logic" and "receives commands from API". That is wrong for review writes and is corrected in the F1a documentation PR, citing ADR-009 and the command catalogue (DD-23).
6.2 Event catalogue¶
Classes follow consistency-model §9: (a) derived on read, no fan-out; (b) durable intent written
in the commit transaction and handled by a leased idempotent dispatcher or an ADR-020 operation record;
© best-effort hint (SignalR, change streams) that never carries correctness. Facts are the
immutable records the transaction itself writes. In-process IDomainEvent (Entity.cs:61-74 collects
them until commit; the dispatch is not awaited per DD-03's reading of MongoUnitOfWorkBase.cs:731-739,
UNVERIFIED here) is used only for loss-tolerant effects and only after #3973. New contract: C19.
| Context, aggregate | Event (fact recorded as) | Consumers and effect class |
|---|---|---|
| Evidence, ReviewerStudyEvidence | SessionVersionRecorded (Save, Complete, Fix, Withdraw; FormSessionVersion plus Study version and summary). Owner session: also for PublicationGenerated, MergeResolved, MergeCarriedForward and UnmergeCarriedForward versions, each attributed to its operation; the first start through a route writes ReviewStarted (§4.4) |
Outdated flags, task drift, Needs updating, readiness: (a). FEAT-024 pending entry through the source-write seam: (b). Inline inbox rows, bounded (task holder, requesting reconciler): (b, inline). Slot-claim release and presence replace: in the transaction. SignalR invalidation: ©. Owner session: the pre-commit warning on a Save after Complete lists dependent work and affected authors get one notice each (Q-27): (b, inline) |
| Evidence, SessionDraft | DraftChanged, DraftLeaseTransferred, DraftDiscarded (draft record, audit). Owner session: DraftChanged is a SessionDraftChange entry; DraftLeaseTransferred is superseded with the lease (D2-08); DraftRebased records a rebase onto a superseding version |
Presence dirty hint: ©. LC1 readiness reads drafts: (a) |
| Evidence, ExposureLedger | ExposureRecorded (ledger). Owner session kinds reconciledHintShown, reconciledHintAdopted, discussion exposure, trainingReferenceShown |
Agreement classification, manifests: (a) |
| Screening Outcomes | ScreeningDecisionSubmitted → ScreeningOutcomeChanged (decision revision, ProfileSession version, ScreeningOutcome entry, Study summary); OwnDecisionCorrected (DP2) |
Pool and route recomputation from the summary: (a). StudyLifecyclePolicy transition in the same transaction (StudyLifecycleLedger). Dependent-form claim at Include: in the transaction (D3-19). Statistics: (b). Adjudication inapplicable after correction: (a, vector; superseded by the owner session: the adjudicated final facet stays current and flagged, RS-R58). Owner session: when the outcome's current value changes, the same transaction evaluates every filter whose dependency set holds the profile and writes StagePoolEntered or StagePoolDeparted with the marker update (fact); an extra-review allowance, a ScreeningDiscussion or an AdjudicationTask is created in the transaction when the profile rule says so |
| Screening Outcomes, StudyPoolLedger | StudyEnteredPool (FEAT-011's pool-entry event; ledger; from batch opening, personal grant, import, filter change, dedup reversal, return from retrieval). Superseded by the owner session (5 October 2026), see the next row |
PRISMA boxes 4 and 8, amendment A fixtures: (a) |
| Workflow, HistoryEvent (C20; owner session) | WorkFirstReleased (renamed from StudyEnteredPool; one per Study and stage), StagePoolBaselineMember, StagePoolEntered, StagePoolDeparted, ReviewStarted (facts written in the commit transaction of the change; sweep transitions written by the stage pool sweep operation) |
Amendment A's "made available to screeners" and the "not yet screened" remainder read WorkFirstReleased: (a). Pool history queries, the eligibility explanation and reporting measures M1 to M5: (a). Readiness intent for affected stages: (b). Claim release for reviewers without started work on a departed Study: (b, outbox). Notices to reviewers with started work: (b, inline, capture only). Never read by admission, selection, counts or readiness |
| Screening Outcomes, AdjudicationTask (owner session) | AdjudicationTaskCreated, AdjudicationClaimed, AdjudicationResolved (AdjudicationVersion, final facet, task state), AdjudicationTaskWithdrawn; AdjudicatorAssignmentChanged (assignment version) |
Queues and the adjudication step: (a). Notices to the assignee and to members leaving an assignment: (b, inline, capture only). Pool reevaluation when the final facet changes: fact in the same transaction |
| Screening Outcomes, external sources (owner session, C22) | AIScreeningModelConfigurationVersioned; ExternalScreeningRunValidated; per Study at acceptance ExternalScreeningDecisionAccepted with the changed ScreeningOutcome (cause ExternalScreeningAccepted) |
Pool reevaluation per Study: fact in the per-Study transaction. Run progress: operation record (b). Notices to affected active reviewers: (b, capture only). Agreement and statistics: their own rules |
| Design, AnnotationForm and FormVersionIssue | FormVersionIssued phase 1 (head CAS, policy, operation record); IssuePolicyRevised (FV4; policy generation CAS); ProfileVersionIssued. Owner session: FormVersionPublished and ProfilePublicationApplied history events through the C20 adapter; target-only publications; PublicationCorrected for a guided correction |
Projection rewrite sweep: (b, operation record). Notices through NotificationFanOut: (b). Admission and readiness pause for the form: (a, readers check the operation state). Issue applied or stalled notice to the admin: (b, inline). Owner session: phase 2 writes generated session versions, mapped revisions, result versions and override versions per Study (b, operation record); pool events with cause FormPublicationApplied or ProfilePublicationApplied where accepted values or outcomes change (fact per Study item) |
| Design, StudyTargetOverride (owner session) | StudyTargetOverrideChanged (override version, Study currentEvidence) |
Readiness and capacity: (a). Automatic stage completion: (b, readiness intent). Notices to the reconciler and to reviewers whose reservation Apply anyway released: (b, inline) |
| Design, DesignDraft (owner session) | DesignDraftChanged (DesignDraftChange); DesignDraftDiscarded |
Live updates to other open design views: © only; the change record is the fact |
| Design, DefinitionTemplate | TemplateCopied (copy record). Owner session: CatalogueItemCopied with copy provenance on the project definition; CataloguePublicationRequested and CataloguePublicationDecided |
None. Owner session: the request queue for catalogue administrators: (a) |
| Workflow, Stage | StageSettingsPublished (version); StageCompleting, StageCompleted, StageReopened, ChangeRequested, ChangeDecided (status history, change request) |
Claim revalidation through the D6 conflict flow and claim withdrawal: (b, outbox). FEAT-024 definition-rewrite fence: (b). Queues and badges: (a). Notices inline, with auto-resolve of siblings if D3-23: (b, inline). Owner session: a settings version that activates a new filter version writes the stage pool sweep operation record (b) and a filter-input preparation operation where needed; an automatic Completed stage reopens as soon as remaining work appears (Q-02) |
| Reconciliation, ReconciliationTask | ReconciliationStarted (editor claim); TaskInputsChanged and TaskHeld (derived); AssignmentCreated, AssignmentExpiring, AssignmentExpired, AssignmentReleased (assignment entity; expiring via a scheduler marker); AdditionalReviewRequested, Returned, Withdrawn |
Queues: (a). Inline notices to assignee, previous holder, requested reviewer: (b, inline). Requested-review claim on Study: in the transaction. Owner session: expiry events occur only where an admin enabled expiry (Q-30); an additional-review request writes override versions per Study (§4.5) |
| Reconciliation, StudyGold | GoldSnapshotPublished (snapshot, pointer CAS, task status). Owner session: AcceptedResultVersionCreated (the AcceptedResultVersion that produced the snapshot, with authority and acceptance method) |
Exports and the re-reconciliation flag on overlapping tasks: (a). Statistics: (b). Inline notices to raisers of addressed concerns (QY8): (b, inline). Owner session: filterInputs[] and pool events for filters reading the changed questions in the same transaction (fact); inference recompute for opted-in projects: (b) |
| Reconciliation, QueryWorkItem | ConcernRaised, ConcernResolved (concern, resolution) |
Query queue: (a). Per-raiser notice inline: (b, inline) |
| Identification | CitationRecorded, PublicationLinked, PublicationEnriched (cross-project, clock-stamped), DuplicateReviewed, StudyMerged, StudySplit (operation record, both Study documents), ExternalStepRecorded, RetrievalRecorded, SearchWithdrawn (ledgers). Owner session: StudySplit is superseded; merge and unmerge write StudyMerged (consolidated Study), StudyTombstoned (each input, and the consolidated Study after an unmerge), MergeConflictResolved (per task), StudyUnmerged and StudyRestored, each with the operation as causal operation; StudyFieldSet for a bibliographic StudyVersion; SearchReinstated |
PRISMA and as-of exports: (a). Dedup audit: fact. Retroactive matching after an accepted bibliographic correction: (b, operation). Owner session: notices, claim revocations, the FEAT-024 staged rebuild and pool evaluation follow merge and unmerge activation through durable intents (b); inputs depart pools with STUDY_NOT_CURRENT_MERGED and the consolidated Study enters with cause StudyMerged |
| Membership (owner session) | ContributionExcluded, ContributionExclusionLifted (exclusion records, operation record); ProjectDeleted, ProjectRestored (deletion and restoration records) |
Qualification and readiness read active exclusions directly: (a). Study summary sweep: (b, operation). Candidate-facet recompute and pool events per affected Study: fact per item. Notices: (b, capture only). Deletion releases claims and stops capture: (b, operation) |
| Training (owner session) | TrainingAttemptStarted, TrainingAttemptSubmitted, TrainingAssessed, TrainingAdmissionDecided, TrainingEvidencePromoted |
Trainee and assessor queues: (a). Group admission through the membership contracts with an audit entry: in the transaction. Never a pool, release, target or PRISMA event |
| Platform | ProjectEnrolled, ScopeAdopted (operation), LegacyWriteCaptured (ledger), ProjectionRewritten (operation). Owner session: BaselineConverted, ConversionRolledBack, ConversionQuarantined (C20 types) and conversion-time StagePoolBaselineMember events |
Admission and flag targeting: (a). Adoption manifests: (a) |
| Reporting | PrismaFlowFrozen, ExportManifestRecorded |
None (terminal facts) |
| Any | UI invalidation (InboxChanged, presence, outdated flags) |
© only; never a correctness path |
Owner-session event names that the specifications name (WorkFirstReleased, the StagePool*
types, ReviewStarted, FormVersionPublished, StudyTargetOverrideChanged, StudyMerged,
StudyTombstoned, MergeConflictResolved, StudyUnmerged, StudyRestored,
AcceptedResultVersionCreated, BaselineConverted, ConversionRolledBack,
ConversionQuarantined, ContributionExcluded, TrainingAttemptStarted) keep those names. The other
added names (DraftRebased, the Adjudication* events, AdjudicatorAssignmentChanged,
AIScreeningModelConfigurationVersioned, ExternalScreeningRunValidated,
ExternalScreeningDecisionAccepted, ProfilePublicationApplied as an event, PublicationCorrected,
DesignDraftChanged, DesignDraftDiscarded, the catalogue and training events,
ContributionExclusionLifted, ProjectDeleted, ProjectRestored, StudyFieldSet) are PROPOSALs
introduced here for the F1a naming ADR. Each is an adapter over the immutable record named in brackets
unless the C20 freeze adds it as a HistoryEvent type.
6.3 Command catalogue¶
Template columns: command · intent (ledger IDs) · aggregates written · aggregates read · transaction class (interactive; fenced definition; operation) · receipt (the command ledger record) · events raised (class) · capability (names are placeholders until A-03; Q-03 approved the capability list on 3 October 2026) · host · typed refusals. The full catalogue is the F1a command ADR (§13); these seed rows fix its shape. Every interactive row also writes Study (version bump, summary) when it changes study-scoped evidence or derived state.
| Command | Intent | Writes | Reads | Class | Receipt | Events | Capability | Host | Typed refusals |
|---|---|---|---|---|---|---|---|---|---|
SaveSession |
SL2, SL3 | ReviewerStudyEvidence (version, heads, revisions), SessionDraft (consume), Study (summary, slot claim release, presence). Owner session: admissionBasis on the version; HintExposure and HintAdoption entries carried in the payload; ReviewStarted on a first start through the route; currentEvidence |
AnnotationForm head, Stage settings version, StudyGold references (withdraw only). Owner session: dependent work for the pre-commit warning when the session was completed (Q-27); continuation settings and the latest pool event | Interactive | FormSessionVersion | SessionVersionRecorded |
Review | API | StaleBase, DraftLeaseHeld, Refused (ownership, admission), Locked, Fenced, SizeLimitExceeded, OutcomeUnknown, CommandDigestMismatch. Owner session: ContinuationRestricted, StudyConsolidated, ProjectDeleted; DraftLeaseHeld superseded with the lease |
CompleteSession |
SL2, SF2 | As Save, plus validation. Owner session: under AutoAccept with effective target one and exactly one qualifying candidate, the task input set, system-authored reconciled revisions, a SingleAnnotator AcceptedResultVersion, a gold snapshot and filterInputs[] in the same transaction, or a durable acceptance effect keyed by (task, input set) if the F1a budget refuses that size (RS §4.1) |
As Save, plus ApplicabilityEvaluator fixtures. Owner session: the declared form version's outdatedAnswerCompletion mode and ReconciliationPolicy; the current StudyTargetOverride |
Interactive | FormSessionVersion | SessionVersionRecorded; owner session AcceptedResultVersionCreated |
Review | API | As Save, plus ValidationFailed (names the blocking question), FormVersionNotRenderable. Owner session: OutdatedAnswersBlockComplete (PROPOSAL name) under BlockUntilAddressed |
FixSession |
SF5, SF6 | New incomplete version | Outdated-flag derivation | Interactive | FormSessionVersion | SessionVersionRecorded |
Review | API | As Save, plus StageCompleted (creates a change request instead, LC1) |
WithdrawSession |
C5 | Withdrawal version; Study (claim release) | StudyGold, task pins | Interactive | FormSessionVersion | SessionVersionRecorded |
Review (or Admin per the C5 ADR) | API | PinnedByGold, PinnedByTask |
AutosaveDraft, TakeOverDraft, DiscardDraft |
SL1, D2-08 | SessionDraft only. Owner session: one SessionDraftChange plus the draft head by CAS on draftVersion; the first autosave also upserts the session and writes ReviewStarted (outside the Study transaction); TakeOverDraft is superseded with the lease (a take-over presentation is a brief detail) |
— | Interactive (no Study) | None (write sequence) | DraftChanged, DraftLeaseTransferred, DraftDiscarded |
Review | API | DraftLeaseHeld, StaleAutosave (owner session: a change to an answer that moved since its base becomes a recoverable conflict copy; a superseded base is rebased, RD-R24) |
SubmitScreeningDecision, CorrectOwnDecision |
DP3, DP2, PR1 | Decision revision, ProfileSession version, ScreeningOutcome, Study (summary, dependent claim), StudyLifecycleLedger, StudyPoolLedger (if availability changes). Owner session: StudyPoolLedger is superseded; the same transaction writes StagePoolEntered or StagePoolDeparted for filters reading the profile, the tracking marker, ReviewStarted on a first start, WorkFirstReleased for entries into an active unbatched stage with remaining work, and where the profile rule says so an extra-review allowance, a ScreeningDiscussion or an AdjudicationTask |
ScreeningProfile version, PrismaPhaseMapping. Owner session: the stage settings version (filter, steps, exclusion-stop, continuation), the tracking marker, open discussion or adjudication | Interactive | ProfileSession version | ScreeningDecisionSubmitted, ScreeningOutcomeChanged; owner session pool events |
Screen | API | As Save, plus EnoughReviewers (dependent claim refused, decision kept), StaleProjection. Owner session: StepLocked, TerminatedByExclusion, ContinuationRestricted. A submission is never refused because its own result removes the Study from the pool (SP §4.2) |
AcquireClaim, ReleaseClaim |
RA1, D6 | Study (claim set, FEAT-024 part or fold entry) | Stage settings, membership facts | Interactive | None (natural key) | Claim revocation via outbox on release paths | Review, Screen, Reconcile | API, PM (timers) | AtCapacity, EnoughReviewers, NotAdmitted, StepLocked, StageCompleted |
IssueFormVersion (phase 1) |
FV1–FV3, PS1–PS3 | AnnotationForm head (CAS), FormVersionIssue, operation record, NotificationFanOut | C8 usage evidence at the fence, preview digest | Fenced definition | FormVersionIssue | FormVersionIssued |
Publish | API | PublicationInProgress, StaleUsageEvidence, PreviewDigestChanged, FormVersionNotRenderable, SizeLimitExceeded |
ReviseIssuePolicy (FV4) |
FV4 | FormVersionIssue (policy generation CAS) | — | Fenced definition | FormVersionIssue | IssuePolicyRevised |
Publish | API | PolicyGenerationStale |
ApplyIssuePolicy (phase 2) |
FV2, FV3 | Study summaries, FEAT-024 rows (projection rewrite), operation record. Owner session (D2-01 amended): per Study item, generated session versions (deterministic ID per session, operation and generation; CAS on each session head), mapped revisions, result versions under the confirmed result treatment, override versions under the confirmed override treatment, currentEvidence, pool events where accepted values change, notice intents |
Predicate over sessions. Owner session: the recorded generation table and treatments | Operation | Operation record | ProjectionRewritten; owner session SessionVersionRecorded per generated version |
System | PM | Fenced (lease lost), StalledAtLimit (D2-10; limits measured, earlier figures proposed, not approved) |
IssueProfileVersion |
Q-26 | ScreeningProfile head, ProfileVersionIssue. Owner session: the ProtocolAmendment entry when eligibility changes (D4-05); phase 2 writes generated profile-session versions and recomputed outcomes per Study under the chosen treatment |
Decisions under prior versions. Owner session: mismatches with existing decisions, outcomes and adjudications by exact version; source policies and model configuration versions (C22) | Fenced definition | ProfileVersionIssue | ProfileVersionIssued |
Publish | API | As IssueFormVersion. Owner session: AmendmentRequired (PROPOSAL name) when an eligibility change has no amendment entry |
PublishStageSettings |
PV2, RX2 | Stage (new settings version, pointer). Owner session: the embedded filter version; the stage pool sweep operation record (durable intent); a filter-input preparation operation before activation when a new question is read | Form and profile versions. Owner session: the preview of entering and departing Studies, affected started work and the completion effect | Fenced definition | StageSettingsVersion | StageSettingsPublished |
Design stage | API | DependencyCycle, StageCompleted (needs a change request), TargetConflict (D6 flow), PreviewDigestChanged |
SweepStagePoolHistory (owner session) |
Q-15, OS-A07, OS-A10 | Per Study: StagePoolEntered or StagePoolDeparted with the activation stamp as effectiveAt and both clause trees, the tracking marker, Study version CAS; operation record |
Studies matching the old or new predicate in stable order; the marker | Operation | Operation record | Pool events | System | PM | Fenced; locked Studies deferred |
ApplyStudyTargetOverride (owner session) |
Consolidation §1; RD-R14 | StudyTargetOverride version, Study (currentEvidence.effectiveTarget), reservation releases if Apply anyway was chosen |
Form version and standard target, current override, qualifying contributions, active places and drafts, task and accepted result | Interactive | Override version | StudyTargetOverrideChanged |
Apply a Study target override (PROPOSAL name; RD §6) |
API | StaleBase, ActiveWorkChanged |
EditDesignDraft (owner session) |
D2-11, OS-A01 | DesignDraftChange, draft head (draftRevision CAS) |
The item's current revision | Interactive (no Study) | Change record (duplicate clientChangeId returns the original) |
DesignDraftChanged |
Design forms and profiles | API | StaleBase (local edit kept) |
CorrectPublication (owner session) |
D2-02 amended; RD §4.13 | A corrected question version (same content, corrected declaration) with a "corrected by" link, then a new form version through IssueFormVersion whose phase 2 generates restoring versions |
The publications that used the declaration and every version and revision they generated | Fenced definition | FormVersionIssue | FormVersionIssued, PublicationCorrected |
Publish | API | As IssueFormVersion |
RequestStageChange, ApproveStageChange, DeclineStageChange |
LC1 | Stage (change request, status) | The underlying change, re-checked at commit | Interactive | Change request | ChangeRequested, ChangeDecided |
Approve stage change | API | AlreadyDecided, RecheckFailed |
CompleteStage, ReopenStage |
RX2, LC1 | Stage (status, history), operation record for the drain | Readiness | Operation (two-step) | Operation record | StageCompleting, StageCompleted, StageReopened |
Manage stage | PM (automatic), API (manual) | NotReady, DrainTimeout |
StartReconciliation |
RA1 | ReconciliationTask (editor claim, session). Owner session: the presentation mapping when the session has none | Candidates, readiness. Owner session: the form version's blinding mode; the override grant | Interactive | None (claim CAS) | ReconciliationStarted |
Reconcile | API | TaskHeld, NotEligible (reviewed the study, unless the override grant applies), NotAssignedToYou |
SaveReconciliation, CompleteReconciliation |
RE2, RE5 | ReconciliationTask (session version), StudyGold (reconciled revisions), SessionDraft, Study. Owner session: on Complete an AcceptedResultVersion (HumanReconciled, Individual, with candidateCount, including one-candidate reconciliation under RequireHumanReconciliation), filterInputs[] and pool events |
Candidate versions, exposure. Owner session: the completeness rule (Q-04), the base snapshot and input-set etags | Interactive | ReconciliationSession version | SessionVersionRecorded (reconciled scope); owner session AcceptedResultVersionCreated |
Reconcile | API | As Save, plus TaskHeld, InputsChanged (re-check); owner session GoldChanged |
BulkAcceptResults (owner session; PROPOSAL name) |
Q-11 | A bulk operation record, then per Study the writes of CompleteReconciliation with acceptanceMethod = BulkConfirmed |
The form's bulkAcceptance setting; Studies where every qualifying candidate agrees; per-Study etags |
Operation (one transaction per Study) | Operation record | AcceptedResultVersionCreated per Study |
Reconcile | API | InputsChanged per Study; excluded Studies per RS-R23 |
PublishGold |
GS1, RE2 | StudyGold (snapshot, pointer CAS), ReconciliationTask (status), affected QueryWorkItems, Study. Owner session: the AcceptedResultVersion that produced the snapshot; filterInputs[]; pool events and the tracking marker for filters reading the changed questions; currentEvidence |
Validity, affected children. Owner session: a pre-commit warning to a reconciler who can see the evidence about stages the Study would leave or enter (counts only, D3-20) | Interactive | GoldSnapshot | GoldSnapshotPublished; owner session AcceptedResultVersionCreated and pool events |
Reconcile | API | StaleBase (pointer), UnresolvedChildren, ValidationFailed; owner session GoldChanged |
AssignTask, ReleaseAssignment, OverrideExpiry |
RA2–RA4 | ReconciliationTask (assignment, editor claim via outbox) | Eligibility | Interactive | Assignment entity | AssignmentCreated, AssignmentReleased |
Assign reconciliation | API | NotEligible, StartedCannotExpire |
RequestAdditionalReview, ReturnAdditionalReview, WithdrawRequest |
RA5 | AdditionalReviewRequest, Study (requested-review claim). Owner session: RequestAdditionalReviews (batch) writes the request record and, for large selections, an operation record; per Study one transaction with a StudyTargetOverride version (basis AdditionalReviewRequest), a scoped assignment per named member or group and the Study write, idempotent per (request, study) |
Target, eligibility. Owner session: per Study the standard target, override, qualifying count and each assignee's eligibility | Interactive (owner session: operation for large selections) | Request record | AdditionalReviewRequested, Returned, Withdrawn; owner session StudyTargetOverrideChanged per Study |
Request an additional review | API | NotEligible, AlreadyRequested |
AdjudicateProfileDecision |
RX1, DP5 | ProfileAdjudication (version), ScreeningOutcome (final facet), Study, StudyLifecycleLedger. Owner session: the AdjudicationTask (state Resolved, claim release) and its AdjudicationVersion with the rationale when required; pool events |
Decisions, must-agree answers, input vector. Owner session: the current assignment version, the profile blinding mode, the rationale rule | Interactive | AdjudicationVersion | ScreeningOutcomeChanged; owner session AdjudicationResolved |
Reconcile (profile part) | API | StaleProjection, InputVectorSuperseded (owner session: InputsChanged with the draft kept, RS-R58; RationaleRequired, PROPOSAL name) |
ClaimAdjudication, SetAdjudicatorAssignment (owner session; PROPOSAL names) |
Tie and adjudicator amendments (OS-A13) | Claim: the editor claim on the AdjudicationTask. Assignment: a new AdjudicatorAssignmentVersion and any claim releases chosen through Apply anyway |
Eligibility, the current assignment; for assignment changes the claimed tasks held by members who would leave | Interactive | Claim CAS; assignment version | AdjudicationClaimed; AdjudicatorAssignmentChanged |
Reconcile (profile part); Manage stage or profile for assignment | API | TaskHeld, NotEligible, NotAssignedToYou; ActiveWorkChanged |
RaiseConcern, ResolveConcern |
QY1–QY9 | QueryWorkItem (concern, resolution, editor claim) | StudyGold pointer | Interactive | Concern or resolution record | ConcernRaised, ConcernResolved |
View answer (raise); Query review (resolve) | API | TaskHeld, StaleTarget |
OpenSharedBatch, GrantPersonalBatch |
Amendment A, D3-13e | Batch plan (CAS), StudyPoolLedger (owner session: superseded by a WorkFirstReleased HistoryEvent for each Study's first release; later openings stay in the plan's own records) |
Completion evidence | Interactive (CAS) | Plan or access row | StudyEnteredPool (owner session: WorkFirstReleased) |
System or Manage stage | API, PM | FrontierStale |
RecordExternalStep, RecordRetrieval, WithdrawSearch |
Amendments K, M, J | ExternalStepLedger, StudyLifecycleLedger, Study (retrieval status), SystematicSearch | — | Interactive | Ledger entry | ExternalStepRecorded, RetrievalRecorded, SearchWithdrawn |
Manage searches | API | Refused (ownership) |
LinkPublication, ReviewDuplicate |
Amendments N, L | Publication, Study (publicationId), DuplicateReviewItem, DedupAuditLedger |
DOI/PMID indexes | Interactive | Ledger entry | PublicationLinked, DuplicateReviewed |
Manage studies | API, PM (import) | PrivacyRefused |
MergeStudies, SplitStudies |
Amendment D, L; D2-12 | Both Study documents (alias, mergedInto), DedupAuditLedger, operation record |
Claims, drafts, open tasks | Operation | Operation record | StudyMerged, StudySplit |
Manage studies | PM | StudyBusy, Fenced. Superseded by the owner session (5 October 2026; D2-12 replaced), see the next rows and C21 |
PrepareStudyMerge (owner session) |
Consolidation §2; DM §4.1 | StudyMerge header (Draft or AwaitingResolution) with the reserved consolidated ID, manifest items, conflict tasks, preview and active-work digests |
Each input's state, StudyVersion, currentEvidence, sessions, results, outcomes, overrides, drafts, claims, tasks |
Interactive (no input written) | Merge header | None until commit | Manage studies | API | StudyConsolidated (an input is not current); a Study already in an active merge (unique partial index) |
ResolveMergeConflict, DelegateMergeConflict (owner session) |
DM §4.2, §4.3 | The task's working state, resolution, resolver and time; delegation record and notice | The task's exact input versions, rechecked as current | Interactive | Task resolution | MergeConflictResolved (at commit) |
Manage studies; the delegated reviewer for their own inputs | API | Stale (inputs changed); delegation refused when the reviewer lost access |
CommitStudyMerge (owner session) |
DM §4.5 | Staging (operation): consolidated StudyVersion 1, carried and resolved sessions with heads and revisions, result versions, merge-basis override, retrieval events. Activation (one transaction): consolidated Study, input tombstones and claim removal, frozen manifest, events and durable intents |
Every input in the activation snapshot (state, StudyVersion, evidence watermark, Audit.Version), the active-work digest |
Operation (staging) plus one activation transaction | Merge header | StudyMerged, StudyTombstoned |
Manage studies | PM | InputsChanged, ActiveWorkChanged, Locked |
PrepareStudyUnmerge, CommitStudyUnmerge (owner session) |
DM §4.9, §4.10 | StudyUnmerge with items; staging of moved copies and restored StudyVersions; activation tombstoning the consolidated Study, restoring inputs, linking copies, currentEvidence, events and intents |
The manifest, post-merge items, active work on the consolidated Study | Operation plus one activation transaction | Unmerge record | StudyUnmerged, StudyRestored, StudyTombstoned |
Manage studies | PM | InputsChanged; refused while the consolidated Study is an input of a later merge; "both" refused |
SetStudyField (owner session) |
DM §4.11 | A new StudyVersion with the field's origin, the Study's projection fields, a history event |
The current StudyVersion and linked references |
Interactive | StudyVersion | StudyFieldSet |
Manage studies | API | StaleBase, StudyConsolidated |
FreezePrismaFlow |
PR1, amendments | PrismaFlowSnapshot | Ledgers, outcomes, mapping | Interactive | Snapshot | PrismaFlowFrozen |
PRISMA | API | CoverageIncomplete (labelled, not refused) |
EnrolProject, RemoveEnrolment |
R0 | CanonicalEnrolment | Rule | Interactive | Enrolment record | ProjectEnrolled |
Application admin | API | NeverChangesOwnership (no refusal; audit) |
AdoptScope |
R6 | CanonicalOwnership, markers on Project and every Study of the scope, LegacyIdAlias, operation record. Owner session: the operation kind is baselineConversion; conversion writes the baseline structures, converted evidence snapshots with legacy-gap states, StagePoolBaselineMember events and BaselineConverted |
Manifest. Owner session: the approved conversion manifest and its inventory checksums, parity report | Operation (lock, verify, stamp, release) | Operation record | ScopeAdopted; owner session BaselineConverted |
Chris (per wave) | PM | ManifestInvalidated, LockContention. Owner session: a conversion that cannot be faithful goes to quarantine, never a lossy forced conversion |
RollBackConversion (owner session; PROPOSAL name) |
BC §4.9 | Clears the ownership markers and registry entry, routes the project back to legacy, writes ConversionRolledBack |
firstCanonicalWriteAt (must be null, same CAS) |
Operation | Operation record | ConversionRolledBack |
Chris (per wave) | PM | FirstCanonicalWriteExists (PROPOSAL name): forward recovery or containment only |
RecordAIScreeningModelConfiguration (owner session; PROPOSAL name) |
E3, OS-A20 | A new configuration version and the head pointer (base-version check) | Existing configurations | Interactive (no Study) | Configuration version | AIScreeningModelConfigurationVersioned |
Manage AI screening models (PROPOSAL) |
API | StaleBase |
ValidateExternalScreeningRun, AcceptExternalScreeningRun (owner session; PROPOSAL names) |
E3; C22 | Validate: the run in Previewed then Validated with per-row results. Accept: per Study one transaction with the new ExternalScreeningDecision version as current, the Study summary, the changed ScreeningOutcome with composition, an AdjudicationTask where the rules route it, lifecycle transitions and pool events; run progress |
The file, the profile version and source policy, Study identities including merge lineage; at accept, each Study's current state and the source's current decision | Validate: interactive; accept: operation with one transaction per Study keyed by (run, study, decision version) | Run record | ExternalScreeningRunValidated, ExternalScreeningDecisionAccepted |
Import external screening decisions (PROPOSAL) |
API, PM | UnmappedLabel and unmatched rows reported at validation; StudyConsolidated resolved through lineage |
ExcludeContributions, LiftContributionExclusion (owner session; PROPOSAL names) |
O1, D4-20, OS-A24 | The exclusion or lift record and an operation record that sweeps affected Study summaries, recomputes candidate facets and writes pool events | The member's contributions in scope, dependent results, active work (preview digest) | Interactive plus operation | Exclusion record | ContributionExcluded, ContributionExclusionLifted |
Exclude contributions (C10) | API, PM | ActiveWorkChanged |
DeleteProject, RestoreProject (owner session; PROPOSAL names) |
O1, D3-12, OS-A25 | deletionState through Deleting or Restoring, the deletion or restoration record, the Study deletion markers, claim releases, capture stop or restart |
Active work (preview digest); on restore, capacity and eligibility | Fenced operation (deleting, restoring) |
Deletion or restoration record | ProjectDeleted, ProjectRestored |
Delete project; restore through the Deleted projects view | API, PM | ActiveWorkChanged |
StartTrainingAttempt, SubmitTrainingAttempt, AssessTrainingAttempt, PromoteTrainingEvidence (owner session; PROPOSAL names) |
S4, OS-A18 | TrainingAttempt and its training sessions; assessments; admission through group membership with an audit entry; promotion operation creating live versions with promotedFrom |
The pinned reference and policy versions; the retry rules; for promotion the live admission rules | Interactive; promotion is an operation | Attempt or assessment | Training events (§6.2) | Review (attempts); Assess training; Promote training evidence (PROPOSAL capabilities) |
API | RetryNotAllowed, AdmissionRefused (PROPOSAL names) |
Typed refusal catalogue (frozen with C18): StaleBase, RetryableConflict, Locked (LockedByBulkUpdate),
Fenced, OutcomeUnknown, Refused (ownership, enrolment, permission), PublicationInProgress,
SizeLimitExceeded, ConflictedLegacyAnswer, CommandDigestMismatch, FormVersionNotRenderable,
DraftLeaseHeld, StaleAutosave, AtCapacity, EnoughReviewers, TaskHeld, StepLocked, StageCompleted,
StaleProjection, ValidationFailed. Generated through NSwag; AF2 handles each without losing drafts.
Owner-session additions (5 October 2026): InputsChanged, ActiveWorkChanged and
StudyConsolidated (DM); ContinuationRestricted and TerminatedByExclusion (SP); GoldChanged
(RS §4.4); PreviewDigestChanged (already used by publication rows). Names introduced on this page
as PROPOSALs: ProjectDeleted, OutdatedAnswersBlockComplete, AmendmentRequired,
RationaleRequired, FirstCanonicalWriteExists, RetryNotAllowed, AdmissionRefused.
DraftLeaseHeld and StaleAutosave survive only where the brief keeps a take-over presentation;
otherwise a stale autosave is rebased (RD-R24). StudyBusy is superseded with the alias merge.
7. Policy catalogue and value objects¶
7.1 Policies¶
Every policy is a pure Core domain service (ADR-009) with a fixture suite as its conformance test (DD-14). Inputs are facts, never repositories.
| Policy | Inputs | Output | Invoked by | Conformance |
|---|---|---|---|---|
ApplicabilityEvaluator (E23) |
Form version, answers, branch context | Applicable question set; typed errors naming the blocking question | Complete, Needs updating, reconciliation validity, UA1 | FEAT-020's rules file and fixtures shared with AF2 (PH-07) |
SessionEffectiveStatePolicy |
Latest explicit version, its pin map, current published version, recorded policies, per-answer validity | Effective state (qualifying, needs updating, pinned under older version, not applicable) | Admission, qualification, AF2, exports | VA-03 fixtures |
ContributionQualificationPolicy |
Effective state, alias set, eligibility. Owner session: merge lineage instead of the alias set; active ContributionExclusions |
Qualifying contributions, counted once per reviewer across stages and aliases (owner session: across routes and merge lineage; excluded contributions never qualify) | Readiness, tallies, PRISMA | C5, SF2, SF6, DD-08 fixtures; owner session DM-AE07, AC exclusion fixtures |
StepRoutingPolicy |
Stage settings version, own decision, candidateCollective and final facets |
Route availability per step (C6 table) | Admission | Research A12–A16, FX-PRISMA-03a. Superseded by the owner session (5 October 2026) by StageFilterEvaluator and StepProgressionPolicy below; the cross-stage table no longer applies |
WorkAdmissionPolicy |
IReviewMembershipFacts (from the summary or embedded data), claims, settings, grants. Owner session: the stage pool predicate, step progression and exclusion-stop results, continuation basis, batch and allocation scope, in-progress limit |
Allow or deny with reasons and evidence; never creates a vote. Owner session: reasons from the closed set OutsidePool, NoRemainingWork, TerminatedByExclusion, AwaitingPriorStep, AwaitingCollectiveInclude, StageNotActive, StageCompleted, PublicationInProgress, NotAllocatedToReviewer, BatchNotOpen, NoPermission, AtCapacity, InProgressLimitReached, ContinuationRestricted, SavedWorkOnly (appended to AccessDenialReason) |
Selection, reservation, direct access, submit; owner session browsing and the eligibility explanation | The generated eligibility truth table (D3-09), gaining filter, step, exclusion-stop and continuation columns |
CapacityPolicy |
Membership facts, claim set, cap (D3-17), target, requested-review claims. Owner session: the form CapacityCap, the route cap, the effective target |
Place available, place held, enough reviewers | Claim acquisition | AC-R2a-35, 36, 37 and 06; AC-R4a-38 |
CollectiveOutcomePolicy |
Profile version rules, decisions, adjudication, input vector. Owner session: sufficiency rule, Unsure, tie policy and bound, discussion state, accepted external decisions under the ScreeningSourcePolicy, active contribution exclusions |
ScreeningOutcomeValue (owner session: with resolutionState, finalSource and composition fields; order-independent; the RS §5.10 transition table) |
Submit, correct, adjudicate, sweep; owner session external acceptance and exclusion sweeps | Parity fixture (VA-20), PR1; owner session the RS §5.10 table and RI-AE26, RI-AE27 |
StageFilterEvaluator (owner session) |
Filter version, Study base predicate, current outcomes and accepted answers (filterInputs[]) |
Three-valued clause tree and membership | Pool predicates, transitions, the sweep, previews | SP fixtures (SP-AE05, SP-AE14, SP-AE16) |
StepProgressionPolicy (owner session) |
Step dependencies, progression basis, own decision, collective outcome, form sufficiency, exclusion-stop settings | Dependency satisfaction, exclusion-stop result and remaining work per reviewer and for anyone | Admission, automatic completion, explanations | The SP §3.4 dependency table (replaces the C6 evaluation table); FX-PRISMA-03ar; C6-T02r, C6-T03r |
ContinuationPolicy (owner session) |
ReviewStarted records, the saved-work and departure settings, the triggers |
Continuation allowed or ContinuationRestricted, with the admission basis |
Save, Complete, decision submit | SP fixtures (OS-A05) |
PoolTransitionPolicy (owner session) |
The tracking marker, before and after evaluations, the cause | Pool events to write, reason codes, episode numbers | Every filter-input writer and the sweep | SP-AE07 to SP-AE11, SP-AE44 |
HintPolicy (owner session) |
The form version's hint baseline, the step override, the gold entry, compatibility, applicability, the reviewer's access | Whether a labelled hint appears and what click-to-fill writes | Reviewer form host | RS hint fixtures (RS-R31 to RS-R38) |
EffectiveTargetPolicy (owner session; PROPOSAL name) |
Current StudyTargetOverride version, current form version's standardTarget |
Effective target with its source | Readiness, capacity, acceptance, statistics | RD-AE08 to RD-AE12 |
TargetOneAcceptancePolicy (owner session; PROPOSAL name) |
Effective target, ReconciliationPolicy.targetOneHandling, qualifying candidates |
Create a SingleAnnotator result, make the task ready for one-candidate human reconciliation, or nothing |
Complete, publication phase 2, contribution exclusion | RS-R01 to RS-R12 fixtures; never accepts two or more candidates |
TrainingScoringPolicy (owner session; PROPOSAL name) |
Training policy rubric, reference version, attempt answers | Per-item scores, overall result, items routed to manual assessment | Submit attempt, re-score | TI-AE03 |
StudyLifecyclePolicy |
Outcomes by profile, PrismaPhaseMapping, retrieval status |
Lifecycle transition or none | The same transaction that writes the outcome (DD-20) | FEAT-011 lifecycle fixtures |
IssueImpactPolicy |
Recorded policy, session category, prior version, compatibility | Treatment per session (requireReanswer, autoUpdate, doNothing, option mapping). Owner session: the generated-version plan per session (at most one per publication generation, combining every question's treatment) under the RD §3.15 table, plus the override and result treatments | Preview, phase 2 sweep, read-time derivation | FEAT-003 categories (PH-18), E1 fixtures; owner session RD-AE16 |
PublicationImpactPolicy |
Task pins, new version compatibility | Which candidates still qualify; inputsChanged or held |
Task drift | DD-07 fixtures |
UsageEvidenceGate |
FEAT-024 usage read at the fence, identity | Current or stale | Issue phase 1 (C8) | PS2/PS3 fixtures |
ReconciliationReadinessPolicy |
Qualifying contributions, target, drafts, corrections. Owner session: the effective target; computed at query time or from a projection proven current for its input versions (Q-27) | Ready, not ready, inputs changed. Owner session: NotReady, Ready, Accepting, Accepted, InputsChanged, BelowCurrentTarget (names PROPOSAL) |
Task creation, LC1 | RE4, SF4 fixtures; owner session RD-AE07 (a stale projection never admits a start) |
PrefillPolicy |
Candidate answers, exact-text match, choice agreement | Prefill with provenance and autofill marks | Reconcile host | RE2, RE5. Owner session: unchanged for the reconciler's workspace; it never prefills a reviewer's own form, where hints need click-to-fill (HintPolicy) |
GoldOwnershipPolicy |
Overlapping forms, existing snapshot | Owner task; second task revises with provenance | PublishGold | D2-09 fixtures |
ExposurePolicy |
Snapshot availability, ledger entries | Three states, failing safe; questioned kind |
Agreement, manifests | C3, NS-06 fixture |
DisclosurePolicy |
Recipient, project, stages, channel (read, export, statistics, inbox, email, digest, presence), BL1, VS1, role | Shaped view | Every channel | NS §4.2 fixtures per kind and role; RT AC-T-08 |
BlindingPolicy |
Stages reaching the task (superseded by the owner session: the form version's or profile version's identityBlinding) |
Most restrictive BL1; alias scheme (superseded: blinded by default; context-local random aliases and order per reconciliation session, no continuity across Studies) | Reconcile host, threads, exports | Q-28 fixtures; owner session RS-R24 to RS-R30 |
StageCompletionPolicy |
Readiness, drafts, corrections, change requests | Completing, completed, blocked | CompleteStage (E29) | Lifecycle fixtures (Q-02) |
CanonicalOwnershipGuard |
CanonicalScopes, the writer's declared scope |
Write filter; refusal explanation | Every legacy writer; composite IAggregateWriteGuard |
StudyWriteLockArchitectureTests extension |
AliasResolutionPolicy |
Alias set, mergedInto |
Primary study and attributed records | Reads, candidate selection, statistics, PRISMA | V2-02 and L.4 fixtures. Superseded by the owner session (5 October 2026; D2-12 replaced): removed; current queries filter on Study.state and redirects follow consolidatedInto; distinct counting follows merge lineage (C21) |
AgreementPolicy (E9) |
Candidate revisions, exposure, method. Owner session: hint adoption markers, initial independent observations, source class (human independent, human informed, external human, machine), training-input flags | Figures, denominators, independent and informed split (owner session: each source class separate; blank is "not assessed") | R5c | Q-04, Q-16 fixtures; methods wait for T-SI-02 |
7.2 Value objects frozen at F1a¶
Shared-kernel types are jointly owned by the contexts named and have a joint conformance suite; the rest are context-local. Equality is by value unless stated.
| Value object | Fields | Equality and rules | Shared kernel |
|---|---|---|---|
AnswerContextKey + ContextKeyHash |
project, study, authorScope, definitionOwner, questionId, entityPath, populationRef; the hash is SHA-256 over a versioned canonical serialisation | Value equality on the ordered fields; unique indexes use the scalar hash only, with partial unique indexes per kind (VB-05) | Evidence, Design, Classification, Reconciliation |
EntityPath |
Ordered elements, each typed optionBranch(optionId) or instance(labelHeadId) (PH-16) |
Element-wise equality including kind | Evidence, Classification |
AuthorScope |
candidate(investigatorId) or reconciled. Owner session: training(attemptId) (PROPOSAL), which every live query excludes |
Value | Evidence, Reconciliation; owner session Training |
DefinitionOwner |
project or profile(profileId) (DD-26's definition ownership; owningParent is a revision edge, not a key part) |
Value | Design, Evidence |
Provenance |
stage, step, settings version, question version (AuthoredUnder may be Unknown), shown revision, real actor, on-behalf-of, source system, legacy ID, mapping version, historyCoverage. Owner session: adoptedFrom (hint adoption), promotedFrom (training), derivedFrom (system-authored SingleAnnotator revisions), merge or unmerge reference with exact source versions, the generating operation and generation for generated versions, copiedFrom |
Value; migration time is never presented as original time | Evidence, Reconciliation, Reporting |
ExposureState |
enum (noGoldAvailable, recorded, availableUnrecorded) plus evidence | Value; fails safe | Evidence, Reporting |
AuthorityValue |
candidateAgreement, reconciled, adjudicated, adminOverride, verified (D4-03), imported (D4-14), legacyUnknown | Closed set stored as strings. Superseded by the owner session (5 October 2026), split into the next two rows: candidateAgreement, reconciled, adminOverride, verified, imported and legacyUnknown leave the closed set; Imported survives only as a candidate provenance kind for mapped human imports (RI §3.10) |
Screening Outcomes, Reconciliation, Reporting |
AcceptedResultAuthority (owner session) |
SingleAnnotator (system rule), HumanReconciled, Adjudicated (profile-owned screening annotations), MergeResolved |
Closed set stored as strings; carried by AcceptedResultVersion.authority; a carried result keeps its original authority (RS §3.2) |
Reconciliation, Reporting |
OutcomeFinalSource and OutcomeComposition (owner session) |
finalSource ∈ ProfileRule, Adjudicated, MergeResolved; composition machineContribution ∈ {None, Contributing, Sole} and externalHumanContribution (boolean) |
Closed sets; derived at commit from the inputs the outcome rests on; external and AI decisions resolve through ProfileRule under their source policy, a human resolution through Adjudicated (RS §3.8; RI §3.13) |
Screening Outcomes, Reporting |
ScreeningOutcomeValue |
candidateResult, voteCounts, ruleVersion, finalResult, finalSource, adjudicationRef, freshness. Owner session: resolutionState, the composition fields, the remaining extra-review bound |
Value; readers name a facet | Screening Outcomes, Workflow, Reporting |
StructuredReason |
primary reason, counted reasons, coverage status | Value (Q-22 keeps both shapes possible; owner session: Q-22 decided-amended, the primary reason is template and reporting guidance and several reason questions are supported) | Screening Outcomes, Reporting |
CompatibilityRelation |
same, compatible, incompatible; reason | Value; declared at commit, immutable once pinned (D2-02; superseded by the owner session: SyRF's suggestion, the publisher's explicit declaration with actor and time and the option mapping are immutable from commit; corrections use guided rollback and republication) | Design, Evidence |
DefinitionVersionVector |
Form, profile and question version seqs a derived record was evaluated under | Component-wise comparison; a lower component means stale | Screening Outcomes, Platform, Workflow |
Route |
stage, step | Value | Workflow, Evidence |
ReviewerAlias |
stage-owned alias from one alias source (superseded by the owner session: a context-local alias drawn at random per reconciliation session and per Study, with no continuity across Studies, under the form's or profile's blinding) | Value within a stage (owner session: value within one presentation mapping) | Reconciliation, Notifications |
ClaimKey and Claim |
study, kind, scope, reviewer; plus route, reservedAt, regime, lease | Key equality | Workflow, Evidence, presence programme |
EntityTypeId |
System identities for the seven legacy categories, cohort, outcome measure, experiment; project-defined later | Value | Design, Classification |
Citation |
FEAT-011's fields; identity = citationId; immutable | Identity by citationId | Identification |
StudyAliasEntry |
secondary study, operation, provenance | Value. Superseded by the owner session (5 October 2026; D2-12 replaced): removed; merge lineage lives in StudyMerge, Study.consolidatedInto and the HistoryEvent lineage field |
Identification, Evidence |
CanonicalScopes |
Set of scope references (form(F), profile(P), notifications) |
Set equality | Platform, every writer |
CoverageLabel, Watermark, HlcStamp, CommandId, ContentDigest |
As named; the watermark is a clock stamp with bounds | Value | Reporting, Platform, Evidence |
LegacyGap (owner session) |
{state, reason, manifestId} with state ∈ NotRecordedInLegacy, CurrentSnapshotOnly, UnknownLegacyAuthor, UnknownLegacyTime, UnknownAuthoredUnderDefinition, ValueOrDefaultUnknown, LegacyCompletionUnvalidated |
Value attached to the field or record that lacks the information (historyCoverage, authorKnown, nullable originalTime, authoredUnder, valueCertainty, completionValidation, the C20 coverage field); never an answer value, so Unknown, Not reported, Not applicable and blank stay distinct (R4; BC §3.2) |
Platform, Evidence, Reporting |
HistoryEnvelope fields, ClauseEvaluation, ReasonCode, CauseKind (owner session) |
The C20 envelope (§4.2 HistoryEvent row); the clause tree {nodeId, kind, result (True, False, Unknown), inputs [{kind, ref, version, observedValue}], children}; closed reason and cause sets |
Value; closed sets extended append-only through C20 | Workflow, Reporting, every writer of history |
AdmissionBasis (owner session) |
List of InPool, ContinuationAfterExclusion {outcomeVersion, settingVersion}, ContinuationAfterDeparture {departureEventId, settingVersion} |
Value; both continuation entries appear when both triggers applied (SP §3.8) | Workflow, Evidence |
FieldValue and FieldOrigin (owner session) |
{value, origin, decidedBy, decidedAt, confirmation}; origin ∈ InheritedFromReference(citationId), SelectedFromReference(citationId), ManualOverride, SystemRule(ruleId, ruleVersion); confirmation SystemOnly or ConfirmedBy(actor, at) |
Value per bibliographic field of a StudyVersion (DM §3.2) |
Identification, Reporting |
EffectiveTarget (owner session) |
value, source (StandardTarget(formVersionSeq) or Override(overrideVersion)) |
Derived, never stored as a fact; projected in currentEvidence |
Design, Workflow, Reconciliation |
CopiedFrom (owner session) |
{catalogueId, itemId, versionId, copiedBy, copiedAt}, or a reference or result source for training references |
Value on the copy; a copy never changes with its source | Design |
8. Ubiquitous language¶
Internal names are PROPOSALs for the naming ADR at F1a; user-facing terms are recommendations pending
D3-03 (copy deck) and are checked against the copy contract (ux-strategy.md). The table resolves the
collisions DD-11 listed. Owner session (5 October 2026): D3-03 is decided-amended, so the meaning of
each term is fixed and the exact words may iterate (U1); superseded rows are kept and marked, and the
owner-session terms are added at the end of the table.
| User-facing term (recommended) | Internal name | Never use it for |
|---|---|---|
| Publish a form or profile version | FormVersionIssue, ProfileVersionIssue |
FEAT-011 Publication; FEAT-024 ProjectStatisticsPublication* |
| Publication (bibliographic) | Publication (Identification namespace only) |
The act of publishing a definition |
| Primary and secondary study (dedup). Superseded by the owner session (5 October 2026): "consolidated Study and input Studies" (row below) | primaryStudyId, StudyAlias, mergedInto |
"canonical" |
| Canonical path, canonical scope | CanonicalEnrolment, CanonicalOwnership, CanonicalScopes |
Dedup primaries; FEAT-024's "canonical tuple" |
| Screening result | ScreeningOutcome {candidate, final}; ScreeningOutcomeSummary on Study (FEAT-011's screeningOutcomes[]) |
Measured outcomes; concern resolutions |
| Outcome measure, outcome data | OutcomeMeasure, OutcomeSchema, Observation |
Screening |
| Concern and its resolution | Concern, ConcernResolution |
"outcome" |
| Screening profile | ScreeningProfile |
FEAT-024 AnnotationStudyProfile (a rename there is a FEAT-024 request); #2987 AnnotationProfile (not harvested); investigator profile |
| Enrolment (a project joins the canonical path) | CanonicalEnrolment |
Work admission; upload admission; FEAT-024 checkpoint admission |
| Work admission (may this reviewer do this now) | WorkAdmissionDecision |
Enrolment |
| Correction (DP2, Fix, LC1, bibliographic) | OwnDecisionCorrection, FixTransition, PendingChange, BibliographicCorrectionEvent |
StudyPdfCorrection |
| Population (animals) | AnimalPopulation |
FEAT-024's search-population family; the review population (box 1) |
| PRISMA flow report | PrismaFlowSnapshot |
PRISMA "reports" (the bibliographic unit, amendment B); study issue reports; reported counts (ExternalStepLedger) |
| Session (a reviewer's work on a form) | FormSession, ProfileSession, ReconciliationSession; presence stays ReviewSessionConnection |
Legacy AnnotationSession once adopted |
| Release (an assignment) | AssignmentRelease |
R-releases; batch release (SharedBatchOpened); pool availability (StudyEnteredPool; owner session: first release is WorkFirstReleased); BulkPdfUploadReleaseRecord |
| Accepted answers (gold standard) | StudyGold, GoldSnapshot; owner session AcceptedResultVersion |
"reconciled" as a status word (use AuthorityValue; owner session: use AcceptedResultVersion.authority) |
| Save progress; Complete | SaveSession, CompleteSession |
"Save draft"; "All changes saved" |
| Changes kept, not yet saved. Superseded by the owner session (5 October 2026): "Draft auto-saved" (row below) | SessionDraft (draft-changes flag) |
A version |
| Needs updating; Outdated answers; Fix | NeedsUpdating (derived), outdated flag (derived), FixSession |
"contains outdated annotations" in UI copy |
| Review place (a reviewer's held place on a study) | Claim (formSlot, profileSlot) |
Assignment; draft lease |
| Reconciling (editing a task) | taskEditor claim |
Capacity claim |
| Stage | Stage aggregate (Workflow) for canonical projects; Project.Stage entity (legacy) |
A step; a form |
| Ledger | *Ledger (append-only facts) |
An aggregate with a current pointer |
| Operation | ADR-020-shaped record with lease and generation | A command; a transaction |
| Draft auto-saved (illustrative wording; owner session) | SessionDraft with its SessionDraftChange log |
A version; a submission; "Autosaved, not yet submitted" |
| Version checkpoint saved (illustrative wording; owner session) | A Save FormSessionVersion |
Completion; a draft |
| Consolidated Study; input Studies (owner session) | The consolidated Study and the tombstoned inputs of a StudyMerge |
"Primary" and "secondary"; an alias; two current Studies |
| Unmerge (owner session) | StudyUnmerge |
Split; deleting the merge |
| Distinct report (owner session) | A DuplicateReviewItem outcome; grouping deferred |
A duplicate; a merge |
| Stage study filter (owner session) | StageStudyFilterVersion |
A stage-entry gate; a reviewer rule; a screening exclusion |
| Stage pool (owner session) | Derived set of current Studies matching the filter | A list of reviewed Studies; a permission |
| Reviewer study pool (owner session) | ReviewerStudyPool (derived) |
An assignment list; a reservation |
| Saved work (outside the pool; owner session) | Continuation under the saved-work and departure settings | Pool membership; a new review |
| Work first released (owner session) | WorkFirstReleased |
Stage pool entry; a review start |
| Stopped by exclusion (owner session) | Exclusion-stop result (TerminatedByExclusion) |
A filter departure; a deletion |
| Adjudication step (owner session) | System-defined step serving AdjudicationTasks |
A stage-entry dependency; extra review |
| Single annotator (accepted automatically) (owner session) | AcceptedResultVersion.authority = SingleAnnotator |
"Reconciled", "verified" or "checked" |
| Reconciled (one candidate) (owner session) | HumanReconciled with candidateCount = 1 |
"Verified" |
| Use accepted answer (owner session) | Hint click-to-fill (HintAdoption) |
Prefill; an independent answer |
| AI screening model; AI-model-generated screening decision (owner session) | AIScreeningModelConfiguration; ExternalScreeningDecision with source type AIScreeningModel |
"Model decision"; a reviewer; a member; a SyRF domain model |
| Standard target; effective target; Study target override (owner session) | FormVersion.standardTarget; EffectiveTarget; StudyTargetOverride |
A capacity cap; a stage setting |
| Capacity cap (owner session) | CapacityCap; route cap |
The target |
| Excluded from current use (owner session) | ContributionExclusion |
Deletion; withdrawal; loss of access |
| Deleted project; restore (owner session) | Project.deletionState; restoration record |
Permanent erasure |
| Catalogue (owner session) | CatalogueItem, CatalogueItemVersion |
A live link to project copies |
| Training (owner session) | TrainingStep, TrainingAttempt, TrainingAssessment |
Calibration votes; live evidence |
| Not recorded in legacy, and the other legacy-gap labels (owner session) | LegacyGap states |
Unknown; Not reported; blank |
9. Transactions¶
The commit protocol, the full transaction table (every operation with the records it writes, its
capture mode, its FEAT-024 part and its claim and presence writes, including RT-15's rows and AP-05's
batch rows) and the command-budget tests are in consistency-model.md §4; idempotency in §5; fences and
operations in §7. This page keeps only the invariants and where each one is materialised.
Summary. Interactive commands use one MongoDB transaction (snapshot read, primary, majority write
with journal, maxCommitTime) over the study-scoped aggregates they change plus Study; a stale base is
re-executed from a fresh snapshot within a deadline; retries are free when Study moved only through fold,
claim-token or idle-token writes. Autosave never touches Study. Definition commands run under fences with
O(1) phase 1. Everything else is an ADR-020 operation or a durable intent handled after commit.
| Invariant | Materialised in | A conflict surfaces as |
|---|---|---|
| One contribution per reviewer per study × form | FormSession deterministic ID and unique natural key | DuplicateKey → reload and CAS (two tabs create one session) |
| The latest explicit version is current | FormSession head CAS on version seq | StaleBase (draft kept) |
| One head per context per author scope | {ProjectId, ContextKeyHash} unique; Conflicted state for adopted duplicates |
DuplicateKey → reload; ConflictedLegacyAnswer until Fix or Save |
| Per-study serialisation | Study version CAS in every study-scoped command | RetryableConflict; free retry if only fold, claim or idle writes moved it |
| Capacity and places | Study claim set in an atomic write filter | AtCapacity, EnoughReviewers |
| One editor per task or query | Editor claim CAS plus lease on the aggregate | TaskHeld |
| One active issue per form | Unique partial index on FormVersionIssue (the pmRobRunOperation.ActiveSearch pattern) |
PublicationInProgress |
| Issue phase 1 versus a racing Save | AnnotationForm head CAS; sessions carry pinnedFormVersionSeq; the sweep is a predicate |
A late Save is swept; if the sweep wins first the reviewer gets StaleBase and keeps the draft |
| Gold pointer | StudyGold current-pointer CAS | StaleBase on concurrent PublishGold and ResolveConcern |
| Legacy write to a canonical scope | CanonicalScopes in the write filter; composite guard |
Refused (ownership) as a filter miss |
| Bulk-update lock | Unlocked filter (ADR-020) |
LockedByBulkUpdate |
| A gate never reads a stale projection | DefinitionVersionVector comparison |
StaleProjection (fail closed; the sweep repeats) |
| One draft writer | SessionDraft lease etag and write sequence | DraftLeaseHeld (conflict copy kept); StaleAutosave |
| Exactly-once commands | (ProjectId, CommandId) unique on the output record plus request digest | The original result is returned; CommandDigestMismatch |
| Merge or split never re-keys | Alias set and mergedInto written by an operation that refuses busy studies |
StudyBusy. Superseded by the owner session (5 October 2026) by the next row |
| Merge and unmerge never edit an input's records (owner session) | Staging under the reserved consolidated ID, then one activation transaction that checks each input's state, StudyVersion and evidence watermark and writes each input by CAS on its Audit.Version |
InputsChanged (originals stay current); ActiveWorkChanged; an activation and any command on an input conflict on the input's Study document |
| A Study is in at most one active merge (owner session) | Unique partial index on pmStudyMerge.inputs.studyId for non-terminal merges |
DuplicateKey → refusal |
| A tombstoned Study takes no writes (owner session) | state in the canonical write filter and the R0 floor predicate |
StudyConsolidated (draft kept, redirect) |
| A pool transition is recorded exactly once (owner session) | The stagePoolTracking[] marker read and updated in the same Study transaction; deterministic HistoryEvent IDs inserted with $setOnInsert |
Duplicate key = success; a sweep that finds the marker already at the new version skips the Study |
| A generated version never overwrites a newer reviewer version (owner session) | CAS on the session head against the version the plan used; deterministic version ID per (session, operation, generation) | Recompute against the new head; a replay returns the existing generated version |
| One current external decision per source, Study and profile (owner session) | Current-pointer index on the decision key; acceptance keyed by (run, study, decision version) | A retry writes nothing new |
| One open adjudication task per Study, profile and trigger (owner session) | Deterministic task ID including the generation | DuplicateKey → reload |
| A deleted project takes no review writes (owner session) | The project deletion marker in the composite write guard | ProjectDeleted (PROPOSAL name; draft kept) |
10. Identity and keys¶
- IDs are CSUUID GUIDs. Aggregates with natural keys get deterministic IDs: SHA-256 over a
versioned canonical key, stored as CSUUID (the #3944 precedent). That covers FormSession,
ProfileSession, AnnotationHead (through its key hash), ScreeningOutcome, ProfileAdjudication,
StudyGold, ReconciliationTask, CanonicalEnrolment, CanonicalOwnership, the default AnimalPopulation
and SessionDraft (= its session or task). Owner session additions:
StudyTargetOverride(project, study, form),HistoryEvent(event type, project, idempotency key),ReviewStarted(session, route stage, route step),AdjudicationTask(project, study, profile, trigger, generation), generated session versions (session, operation, generation), carried sessions on a consolidated Study (project, consolidated Study, form, reviewer),TrainingAttempt(project, step, reviewer, attempt number) and converted evidence (project, manifest lineage, legacy ID). The consolidated Study ID is a GUID reserved when the merge is created. Revisions and entity instances use client-proposed, server-validated IDs (unused, same project), so AF2's inline creation needs no ID remapping. Legacy IDs are kept at adoption, with the natural-key unique index as the real guard (VB-16, DD-15). - Context key hash.
contextKeyis an ordered value object stored besidecontextKeyHash; unique indexes use scalars only:{ProjectId, KeyHash}unique, partial unique indexes per kind (for example{ProjectId, StudyId, AuthorScope, ProfileId}where kind = screening decision), and a non-unique{ProjectId, StudyId, AuthorScope, QuestionId}for ancestor and SF5 reads (VB-05). - Kinds and statuses are strings parsed from a closed set, as FEAT-024's pending kinds are, which replaces the "append ordinals, never reorder" rule for canonical records (VB improvement 9).
- Explicit collection names, decoupled from class names, frozen in one map with a test that asserts
it; append-only repositories; content digests (
versioning-model.md, VB-10). The class-name formula (mongodb-reference.md:88) stays for existing collections only. - System question identity:
pmQuestionDefinition._idis a record GUID with{ProjectId, QuestionId}unique, because system question IDs repeat across projects (VB-11).
Collection list (aligned with VB's storage blueprint; VB's pmFormPublishOperation is this page's
pmFormVersionIssue). Identity and unique keys per collection; other indexes are the storage ADR's.
IssuePolicyRecord is embedded in FormVersionIssue, so it has no collection of its own; the F1a naming
ADR confirms. Owner session (consolidation §1): a distinct domain record does not by itself justify a
new collection. The owner-session rows below are PROPOSALs chosen where an append-only repository
must enforce insert-only writes or a query needs its own index; the F1a storage ADR may embed or split
them against measured volume.
| Collection | Identity and unique keys | Context |
|---|---|---|
pmQuestionDefinition, pmQuestionDefinitionVersion |
record GUID; {ProjectId, QuestionId} unique; versions {DefinitionId, Seq} unique |
Design |
pmSystemQuestionVersion |
{QuestionId, SystemQuestionVersion, StructuralDigest} unique |
Design (system) |
pmAnnotationForm, pmAnnotationFormVersion |
{ProjectId, FormId}; versions {FormId, Seq} unique; head holds CurrentPublishedSeq, PublicationSeq, PolicyGeneration |
Design |
pmFormVersionIssue, pmFormVersionIssueChunk |
one active per form (unique partial index); chunks {OperationId, Chunk} unique |
Design |
pmScreeningProfile, pmScreeningProfileVersion, pmProfileVersionIssue |
as forms | Design |
pmDefinitionTemplate |
_id; {Scope, OwnerId?, TemplateId} (owner session: the system scope holds CatalogueItem heads and CatalogueItemVersion documents with a catalogueId dimension) |
Design |
pmOutcomeSchema, pmEntityType, pmSharedConcept, pmProjectRule |
{ProjectId, …Id} unique; versions by seq |
Design |
pmReviewStage, pmStageSettingsVersion |
_id = stage ID; versions {StageId, Seq} unique |
Workflow |
pmFormSession |
deterministic _id; {ProjectId, StudyId, DefinitionOwner, AuthorId} unique (forms and profiles) |
Evidence |
pmFormSessionVersion |
{SessionId, Seq} unique; {ProjectId, CommandId} unique (the receipt) |
Evidence |
pmSessionDraft |
{SessionId} unique; conflict copies by {SessionId, HolderTabId} |
Evidence |
pmAnnotationHead |
{ProjectId, KeyHash} unique; partial unique per kind |
Evidence (candidate), Reconciliation (reconciled scope) |
pmAnnotationRevision |
_id; {AnnotationId, Seq} unique |
Evidence, Reconciliation |
pmExposureLedger |
{SessionVersionId, ShownRef} unique |
Evidence |
pmScreeningOutcome, pmProfileAdjudication |
deterministic _id; {ProjectId, StudyId, ProfileId} unique; adjudication versions by seq (owner session: pmProfileAdjudication holds the AdjudicationTask aggregate keyed {ProjectId, StudyId, ProfileId, Trigger, Generation}, one open per Study, profile and trigger) |
Screening Outcomes |
pmStudyPoolLedger |
_id; {ProjectId, StudyId, HlcStamp} |
Screening Outcomes. Superseded by the owner session (5 October 2026) by pmHistoryEvent |
pmHistoryEvent (owner session) |
deterministic _id; indexes {ProjectId, StageId, EventType, EffectiveAt.Hlc}, {ProjectId, StudyId, EffectiveAt.Hlc}, {ProjectId, SubjectReviewerId, EventType, EffectiveAt.Hlc}; inserts only; no TTL (the storage ADR may split families) |
Workflow and Reporting (C20) |
pmStudyVersion (owner session) |
{StudyId, Seq} unique; append-only |
Identification |
pmStudyMerge, pmStudyMergeItem, pmStudyUnmerge, pmMergeConflictTask (owner session) |
_id; unique partial index on inputs.studyId for non-terminal merges; items {MergeId, Chunk}; tasks indexed by assignee for My work |
Identification (C21) |
pmStudyTargetOverride (owner session) |
deterministic override ID from {ProjectId, StudyId, FormId}; versions {OverrideId, Seq} unique; append-only |
Design |
pmDesignDraft, pmDesignDraftChange (owner session) |
_id; changes {DraftId, DraftRevision} unique; append-only changes |
Design |
pmSessionDraftChange (owner session) |
{SessionId, DraftVersion} unique; append-only |
Evidence |
pmAcceptedResultVersion (owner session) |
{ProjectId, StudyId, FormId, Seq} unique; {ProjectId, CommandId} unique; append-only (or embedded in the task per the storage ADR) |
Reconciliation |
pmSessionPresentation (owner session use) |
{SessionId} unique; for reconciliation {WorkItemId, ReconciliationSessionSeq}; server-only read |
Evidence, Reconciliation |
pmAIScreeningModelConfiguration, pmExternalScreeningRun, pmExternalScreeningDecision (owner session) |
configurations {ProjectId, ConfigurationId, Seq} unique; runs idempotent on {ProjectId, SourceKey, SourceRunId, FileDigest}; decisions {ProjectId, ProfileId, SourceKey, StudyId, Seq} unique with a current-pointer index |
Screening Outcomes (C22) |
pmTrainingReference, pmTrainingReferenceVersion, pmTrainingPolicy, pmTrainingPolicyVersion, pmTrainingAttempt (optionally pmTrainingAssessment) (owner session) |
versions {…Id, Seq} unique; attempts deterministic from {ProjectId, StepRef, ReviewerId, AttemptNumber} |
Training |
pmContributionExclusion, pmProjectDeletionLedger (owner session) |
{ProjectId, ExclusionId}; {ProjectId, Seq}; append-only |
Membership |
pmNotificationContentPolicy, pmCataloguePublicationRequest (owner session) |
{ProjectId, Version} unique; _id |
Notifications; Design |
pmConversionInventory, pmConversionManifest, pmConversionWave, pmConversionParityReport, pmConversionQuarantine, pmRecoveryManifest (owner session) |
per project and run, manifest lineage and version, wave, attempt and quarantine IDs; immutable once approved or written | Platform |
pmDefinitionSettingsAudit (from the versioning model) |
append-only {OwnerRef, Seq}; form, profile and stage operational settings changes, adjudicator assignment versions and the inference beta setting |
Design |
pmReconciliationTask |
deterministic _id; {ProjectId, StudyId, FormId} unique |
Reconciliation |
pmAdditionalReviewRequest |
_id; {TaskId, ReviewerId} unique while open (owner session: reshaped as a batch with per-Study items, idempotent per {RequestId, StudyId}) |
Reconciliation |
pmStudyGold, pmGoldSnapshot |
{StudyId} unique; snapshots {StudyId, Seq} unique |
Reconciliation |
pmQueryWorkItem |
{AcceptedAnswerVersionId} unique |
Reconciliation |
pmAnimalPopulation, pmInferenceResult |
{StudyId, PopulationId} unique (owner session: inference results keyed {ProjectId, StudyId, PopulationId, BasisKind, BasisId, RuleVectorDigest, EngineVersion}, history kept) |
Classification |
pmPublication |
_id; DOI and PMID unique sparse |
Identification (system) |
pmDuplicateReviewItem, pmDedupAuditLedger, pmDedupBatch (TTL staging) |
per FEAT-012 with the ledger rename | Identification |
pmExternalStepLedger, pmStudyLifecycleLedger |
_id; {ProjectId, (SearchId|StudyId), HlcStamp} |
Identification |
pmPrismaPhaseMapping, pmPrismaFlowSnapshot, pmExportManifest, pmAgreementResult |
{ProjectId, …}; snapshots and manifests append-only |
Reporting |
pmCanonicalEnrolment, pmCanonicalOwnership |
{ProjectId} unique; {ProjectId, Scope} unique |
Platform |
pmCanonicalOperation, pmCanonicalOperationChunk |
one active per scope (unique partial index); chunks {OperationId, Chunk} |
Platform |
pmLegacyWriteLedger, pmLegacyIdAlias |
_id; {ProjectId, LegacyId} unique |
Platform |
pmNotificationFanOut |
{SourceId} unique |
Notifications (programme) |
New pmStudy indexes (summary, markers, claims) |
built through the operator route with commit quorum; partial where possible (VB-18) | Study |
11. Modularity for parallel agents¶
- One namespace per bounded context:
Core/Model/<Context>/andCore/Services/<Context>/(ReviewDesign,ReviewWorkflow,Evidence,ScreeningOutcomes,Reconciliation,Classification,Identification,Reporting,Membership,Platform; owner session:Training). The legacy embedded model stays underProjectAggregate/andStudyAggregate/and is reached from new code only throughLegacyReviewDataAdapter. Owner session: the C20 envelope types (HistoryEnvelopefields,ClauseEvaluation, reason and cause sets) andLegacyGapare shared-kernel types underCore/Contracts/, written by each context's own commands. internalby default. Public surface per context is limited toCore/Contracts/<Context>/: shared-kernel value objects (§7.2), policy interfaces (§7.1), repository interfaces and DTOs. Hosts referenceProjectManagement.Application, never a context's internals.- Architecture fitness tests, in the F1a conformance suite:
- a source-scanning test extending
StudyWriteLockArchitectureTests(Mongo.Data.Tests/StudyWriteLockArchitectureTests.cs:25-74,CODE-MAIN; it scans production sources per member with regexes, with an allow-list of justified exceptions) so that every direct Study or Project write adds the ownership filter as it already addsUnlocked, and every write to a registered immutable collection is an insert (noReplaceOne,Update*,Delete*,FindOneAnd*or update models); - a reflection-based dependency test (NetArchTest-style; DD-22 found none in
src) asserting the context map's allowed dependencies, nointernalleakage across contexts, and the hosting rule (command handlers only in Application; no policy with a repository dependency); - the collection-name map test and the append-only repository test (
versioning-model.md). - Lanes map to contexts. L1 Evidence, L2 Design, L3 Screening Outcomes (with L2's editor), L4 Workflow, L6 Reconciliation, L9 Classification, L10 Design (outcome schemas), L11 and L12 Reporting and Identification, L8 Membership, L0 and L15 Platform. A change to a shared-kernel type or another context's contract goes through an ADR amendment with consumer sign-off; one writer per worktree. Owner session: Training and the external and AI screening lane (XS1, proposed ID) get their lanes in the rollout plan; C20 is owned by L4 with L11, C21 by L12 with L1, and C22 by L3 with L12 (contracts §2).
12. Introduction by release¶
Owner-session additions (5 October 2026) are marked in each row; release names follow the
integrated plan and the lane placements are
PROPOSALs for the rollout plan. Placement is planning only: no release has
started and implementation is on hold.
| Release | New aggregates, entities and ledgers | Changed aggregates |
|---|---|---|
| M0 (engine proof) | None persisted; fakes and the conformance suite | — |
| R0 | CanonicalEnrolment, CanonicalOwnership, CanonicalScopes markers |
Study, Project, SystematicSearch value objects capture extra elements; Study getters and the claim pipeline merge CanonicalSummary; PM gains capture capability (E59). Owner session: the composite write guard gains the project deletion marker; the floor step before P2 adds the tombstone predicate |
| R1a | DefinitionTemplate (question templates, with the copy record). Owner session: CatalogueItem, CatalogueItemVersion, CataloguePublicationRequest for questions and forms |
None (R1a adds no Project field, V2-16) |
| R1b | — | Project (owner-only enforcement; no schema). Owner session: named-attribution display and joining-terms text |
| R1c, R1d | — | Project (custom groups, grants, delegation envelope) |
| R2a | QuestionDefinition, SystemQuestionVersion, AnnotationForm (requirement versions, operational settings), Stage (minimal binding), ReviewerStudyEvidence (FormSession, versions, heads, revisions), SessionDraft, command ledger records, LegacyWriteLedger, ExportManifest (version exports), EntityTypeId identities. Owner session: FormVersion.standardTarget and ReconciliationPolicy in the first canonical form version, SessionDraftChange, DesignDraft and DesignDraftChange (single editor), ContributionExclusion (form scope) |
Study (CanonicalSummary, version bump, claim release on first Save), Project (CanonicalScopes), ReviewerPresence (FormSessionId), ReviewSessionConnection (tab ID), DataExportJob (previous versions), StageAllocationRegime (refusal on canonical stages). Owner session: Study currentEvidence per the storage ADR |
| R2b | — | Study (claims v2, form-keyed), ReviewerPresence (form key), ProjectStatistics (form-unique derivations). Owner session: one place across stages, tabs and devices; form-owned timeout, in-progress limit and CapacityCap baseline |
| R2c | FormVersionIssue, operation records (projection rewrite), NotificationFanOut (programme). Owner session: generated session versions and mapped revisions in phase 2, target-only publications, StudyTargetOverride with the publication treatment, design-draft presence and live updates, the shared active-work impact preview |
AnnotationForm head (publication seq, policy generation), ProjectStatistics (usage families) |
| R2d | — | ReviewerStudyEvidence (cross-form sharing, outdated flags derived, Fix), FormVersionIssue (FV4 policy revisions), AnnotationForm (A-19 lifted). Owner session: guided correction (CorrectPublication); D2-09 stays parameterised |
| R3a | ScreeningProfile (default compatibility profile), ProfileSession, ScreeningOutcome, StudyPoolLedger, Stage (steps, routes, filter element). Owner session: HistoryEvent instead of StudyPoolLedger (pool events, WorkFirstReleased, ReviewStarted), StageStudyFilterVersion, step kinds, exclusion-stop and continuation settings, route caps, ContributionExclusion (stage scope) |
Study (ScreeningOutcomeSummary, profile claims, dependent-form claim at Include), ProjectStatistics (decisions, target-aware classification). Owner session: Study canonical summary gains filterInputs[] and stagePoolTracking[] |
| R3b | ScreeningProfile (full), ProfileVersionIssue, PrismaPhaseMapping, DefinitionTemplate (profiles). Owner session: ScreeningProfileVersion settings (Unsure, tie policy and bound, discussion flag, rationale, blinding, sufficiency) with mismatch detection at publication, the reserved ScreeningSourcePolicy slot (refused if populated before XS1), ProtocolRegistration, ContributionExclusion (profile scope), catalogue profiles |
QuestionDefinition (profile-owned), ScreeningOutcome (per profile), ProjectStatistics (profile-version usage, F5) |
| R3c | Stage lifecycle (status, mode, StageChangeRequest, history), operation records (completion drain) | Stage. Owner session: lifecycle per Q-02 (automatic reopening when remaining work appears; manual completion stays until reopened) |
| R3d | Setup drafts (a ProjectSetupDraft record owned by L13, PROPOSAL) |
Project (created canonical by rule) |
| R4a | ReconciliationTask (ReconciliationSession, assignments, editor claim), AdditionalReviewRequest, StudyGold and GoldSnapshot, ExposureLedger. Owner session: AcceptedResultVersion, the presentation mapping, hint exposure and adoption kinds, the self-reconciliation override grant, batch additional-review requests raising targets |
Study (requested-review claim), StudyConversation (task binding, L6 ownership), ReviewerPresence (reconcile host joins). Owner session: task for every form with a qualifying candidate, including target-one forms |
| R4p | ProfileAdjudication. Owner session: AdjudicationTask with AdjudicationVersion (replacing ProfileAdjudication), AdjudicatorAssignmentVersion, ScreeningDiscussion, the system adjudication step |
ScreeningOutcome (final facet, adjudicated authority; owner session: resolutionState, finalSource) |
| R4b | QueryWorkItem (Concern, ConcernResolution, query editor claim) | StudyGold (pending flags) |
| R4c | — | StudyGold (outcome-series gold snapshots) |
| R5a | ExportManifest (as-of, watermark), operation records for long exports | DataExportJob (as-of mode, download ownership) |
| R5c | AgreementResult | — |
| R5b | PrismaFlowSnapshot | Study (metaAnalysisIncluded). Owner session: snapshots read pool history, WorkFirstReleased and review starts with the reporting priority on actual review through the stage (T-SI-05) |
| C1, C2 | EntityType (aggregate), AnimalPopulation, SharedConcept, ProjectRule, DefinitionTemplate (entity types); InferenceResult. Owner session: C2 is an opt-in beta with the project setting, ClassificationRuleVersion and basis-keyed InferenceResult |
ReviewerStudyEvidence (classification assertions; instance membership) |
| O1, O2 | OutcomeSchema, DefinitionTemplate (schemas); O2 staged copies and manifests through operation records | ReviewerStudyEvidence (observation kinds), AnnotationForm (schema bindings) |
| P1 | ExternalStepLedger, StudyLifecycleLedger, Citation records, Publication (if amendment N creates at import). Owner session: StudyVersion for new imports with reference and source-document links |
SystematicSearch (source type and name, withdrawal, documentation fields; owner session: documentationVersions[], reinstatement), Study (citations[], retrieval status) |
| P2 | Publication (otherwise), DuplicateReviewItem, DedupAuditLedger, dedup batch staging, StudyAlias (superseded by the owner session). Owner session: P2a Study state and tombstones, StudyVersion field provenance, StudyMerge and StudyUnmerge for unreviewed duplicates, the CurrentEvidenceView shell; P2b MergeConflictTask, carried and resolved sessions and decisions, target confirmation, unmerge carry-forward; P2c accepted-result and adjudicated-outcome conflicts |
Study (lifecycleStatus, publicationId, duplicateGroupId, mergedInto, aliases; owner session: state, currentVersionId, tombstone, consolidatedInto instead of mergedInto and aliases) |
| AL1 | — | StageAllocationRegime (schema v2, form binding), Stage settings version (regime by ID) |
| GA | — | CanonicalEnrolment rule (new projects by default) |
| R6 | LegacyIdAlias; operation records for cutover. Owner session: universal baseline conversion waves after trials and pilots, with the conversion records of §4.9 and firstCanonicalWriteAt |
Study and Project markers; adopted projections |
| R7 | — | CanonicalSummary retired with the legacy readers; LegacyReviewDataAdapter and legacy embedded types retired. Owner session: a separate verified retirement milestone with its readiness record |
| Training lane (owner session; named in the rollout plan) | TrainingReferenceVersion, TrainingPolicyVersion, TrainingStep, TrainingAttempt, TrainingAssessment, admission and promotion records |
Membership (group admission with audit) |
| XS1 (owner session; proposed lane ID) | AIScreeningModelConfiguration, ExternalScreeningRun, ExternalScreeningDecision; the populated ScreeningSourcePolicy |
ScreeningOutcome (composition fields), AgreementResult (machine class), PrismaFlowSnapshot (machine-assisted share) |
| XA1 (owner session; proposed lane ID) | Annotation-answer import provenance (Imported candidate provenance with mapped reviewer) |
ReviewerStudyEvidence (imported revisions) |
| X-DEL, amended (owner session) | Project.deletionState, ProjectDeletionRecord, ProjectRestorationRecord |
Study (deletion marker); Project |
13. Decided at the freeze gates¶
| Gate | Domain-model decisions taken there |
|---|---|
| F1a (engine contracts) | The ADRs below. In particular: the physical shape of every §4 boundary and of CanonicalSummary (this shape versus VB's stub sessions); draft storage and lease; deterministic IDs and the collection map; the context-key hash; EntityTypeId identities (E14's identity part moves here; its catalogue and alias validation stay at F-C and F-O); the claim contract v2 and the projection shape (the presence and FEAT-024 owners' checklists pass, run by a fresh-context agent; Chris rules on exceptions); the event taxonomy (C19) and the transaction admission ADR (C18); the command catalogue and hosting rule; ScreeningOutcome facet shape; IReviewMembershipFacts; the versioning rulebook (versioning-model.md); E25 settled on M0 evidence; D2-01 to D2-16 answered (owner session, 5 October 2026: D2-01 and D2-02 decided-amended; D2-05 decided-amended in part; D2-07, D2-08 and D2-11 decided; D2-12 and D2-16 replaced; D2-14 and D2-15 decided-amended; D2-03, D2-04 and D2-06 are engineering contracts with no owner question, frozen here; D2-10 and D2-13 are brief items; D2-09 is the one open owner decision). Owner session additions: the C20 HistoryEvent envelope and its storage; the D2-05 setting classification table (RD §3.5); the CurrentEvidenceView shape once its proof passes (or at F-P); the AuthorityValue split; the LegacyGap value object |
| F1b (catalogue and export disclosure) | The Q-03 capability catalogue subset; DisclosurePolicy channels including presence (D3-20) and notifications; the study-issue and PDF-correction capabilities (NS-20); export disclosure (U26); D11 download ownership. Owner session: Exclude contributions, Deleted projects view and restore, catalogue administrator role, notification settings, the self-reconciliation override grant, the adjudication capability, the training capabilities and the model metadata view (PROPOSAL names) |
| F1c (IA, copy, AF2 seams) | The glossary's user-facing column (D3-03, D3-04); AF2 extension points including VersionedAnnotationFormDataSource and the Needs-updating presenter; the Dockview layout-contract amendment; the save-status state machine. Owner session: D3-03 and D3-04 decided with wording flexibility; "Draft auto-saved" and "Version checkpoint saved" stay distinct; the shared active-work impact preview DTO |
| F2 (publication) | FormVersionIssue phases and the predicate sweep (E22); FEAT-024 usage families and scope kinds (MS-02); Q-34 option mapping; impact-manifest categories (PH-18); the scoped pause limit (D2-10). Owner session: the generation table and the draft rebase rule (RD §3.15, RD-R24); target-only publications and the override treatment; guided correction; collaborative design drafts |
| F3 (workflow) | The Stage aggregate and the settings placement table (E62); the filter element's schema (FEAT-008 filter set); ScreeningOutcome frozen with amendment H; StudyLifecyclePolicy; Q-24, Q-15, Q-28 mappings; D3-13, D3-17 to D3-19; batch and allocation references by ID (AP-11); the fixed-two correction as a FEAT-024 prerequisite (AP-14). Owner session: Q-15, Q-24, Q-01, Q-02 and Q-28 decided (Q-15 replaced by the stage filter and step model); filter schema v3 with three-valued evaluation; step kinds; exclusion-stop and continuation settings; the C20 stage-pool and eligibility event types; ReviewStartEligibility; D3-17 and D3-18 carry-forward and D3-09, D3-13, D3-16, D3-19, D3-20 brief items; amendment H's authority list replaced by finalSource plus composition fields |
| F4 (reconciliation) | C9 with the task keyed by study × form (the compatibility-class decision is removed from F4); ReconciliationSession and the editor claim (X-RECLAIM); shared-gold revision (D2-09); drift and held states; legacy authority (Q-35); authority policy (Q-36); target-1 forms (Q-29); the editable reconcile host; ADR-008 absolute timestamps for every new timer (PH-30). Owner session: Q-35 removed; Q-36, Q-11, Q-04 and Q-30 decided; Q-29 and D4-03 decided-amended (AcceptedResultVersion, SingleAnnotator or one-candidate human reconciliation); blinding and presentation mapping; hints; D2-09 still open |
| F5 (profiles) | ProfileVersionIssue treatment (Q-26); ProfileSession shape; keyword-list ownership (PH-28); the screening renderer contract; profile-version usage family; D4-01, D4-02, D4-13 options in profile versions. Owner session: Q-26, D4-01 and D4-02 decided, D4-13 and Q-22 decided-amended; the ScreeningProfileVersion settings including the tie policy; the reserved ScreeningSourcePolicy slot; the AdjudicationTask shape |
| F6a (as-of) | Watermark semantics over clock stamps; manifest retention (stored, PROPOSAL); coverage labels; D2-13 restore and D2-14 erasure as they affect manifests. Owner session: the history watermark rule for C20 datasets; erasure in manifests conditional on T-POL-02 |
| F6b (reporting) | PrismaFlowSnapshot manifest; amendments B, E, F; Q-22, Q-23; D4-11 box 1. Owner session: Q-06b and D4-11 decided; Q-23 carry-forward; the stage measures and the reporting priority with T-SI-05 |
| F-P (identification) | Amendments K, M, N, O; Citation storage (embedded or own collection); Publication creation point and privacy rule; retrieval status derivation; search documentation fields (D4-05); D3-12 withdrawal versus history. Owner session: C21 (StudyMerge, StudyUnmerge, MergeConflictTask, StudyVersion field provenance, the consolidated Study identity choice, CurrentEvidenceView); amendment O replaced by prepared links; D4-05 and D4-07 decided |
| F-C (classification) | EntityType capabilities and project-defined types (identities already minted); AnimalPopulation creation at enablement; Q-18, Q-19; E14's catalogue and alias validation. Owner session: Q-18 and Q-19 decided; the inference beta opt-in and basis rule |
| Training freeze (owner session; with F3 for the step kind) | TrainingStep, reference and policy versions, attempts, assessments, admission and promotion |
| XS1 freeze (owner session; proposed) | C22: AIScreeningModelConfiguration, ScreeningSourcePolicy population, ExternalScreeningRun, ExternalScreeningDecision, acceptance semantics |
| F-O (outcomes) | OutcomeSchema versions and supplied schemas as system templates; A-20 confirmed; Q-17; E12 |
| F-A (allocation) | Regime schema v2 and floor; one plan per shared form; the allocation owner's phase mapping (AP-10); AL1 entry after #3269's checklist (AP-23) |
ADRs needed before F1a (DD §3.7 merged with the brief's C18 and C19; numbers come from the block
reserved in delivery-operating-model.md §11.8, ADR-030 to ADR-069; each ADR cites ADR-009 and, for timers, ADR-008):
- Bounded contexts, context map and architecture fitness tests (§2, §11; DD-05, DD-22).
- Evidence aggregate boundary and physical storage, with the collection map and
pmStudyindex build routes (§4.1, §10; DD-01, E15, E28, VB-10, VB-18). - C18 transaction admission, concurrency and idempotency: snapshot reads, re-execution, typed outcomes, the command ledger record, per-study ordering and the clock stamp, as-of bounds (§9; brief §1.2, §1.4, §1.7; replaces DD's separate receipt and history-ordering ADRs).
- C19 durable effects and events: the three classes, carriers, the event catalogue, PM hosting (§6.2; DD-03, NS-01).
- Command catalogue and hosting rule, including the PM capture capability as an R0 item and the
platform-architecture.mdcorrection (§6.1, §6.3; DD-04, DD-23). - Ubiquitous-language glossary and naming, merging the C4 naming ADR and the Q-08 harvest naming, with the user-facing column pending D3-03 (§8; DD-11).
- Compatibility floor with the document-level
CanonicalScopesmarker and composite write guard (§1.7, §4.9; DD-13, VB-07, E16). - Answer context key,
EntityTypeIdidentities, default population and ID minting (§7.2, §10; DD-12, DD-19, DD-24, DD-26, VB-05, VB-16, E27). - Screening-outcome facets and the collective policy, shape at F1a and frozen with amendment H at F3 (§4.2; DD-06).
- The versioning rulebook (
versioning-model.md) and the C15 v2 capture contract (notification programme, NS-03), which this page consumes. - C20 structured history events (owner session): the envelope, closed event, reason and cause sets, idempotency keys, ordering, effective and recorded time and the history watermark, adapters over existing records (§4.2; SP §3.12). Envelope at F1a; stage-pool and eligibility types at F3.
- C21 duplicate consolidation and reversal (owner session): Study parent state,
StudyVersion, merge and unmerge operations, conflict tasks and the current evidence view (§4.7; DM). At F-P, after the current evidence view proof. - C22 external and AI-model screening sources (owner session): model configurations, source policies, runs, decisions and outcome composition (§4.2; RI §3.11 to §3.14). Slot reserved at F5; the contract freezes before XS1.
14. Relationships¶
Cardinalities show legacy projects: canonical aggregates are zero-or-one or zero-or-many until a project is enrolled (V2-26).
Owner-session changes to the diagram (5 October 2026): the round-2 edges STUDY |o--o{ STUDY :
"mergedInto (alias, never re-keyed)" and STUDY ||--o{ STUDY_POOL_LEDGER : "pool entries" are
superseded and replaced by the STUDY_MERGE, STUDY_UNMERGE and HISTORY_EVENT edges below;
PROFILE_ADJUDICATION is shown as the ADJUDICATION_TASK aggregate that replaces it; the draft edge no
longer carries a lease. The remaining new edges are additions.
erDiagram
PROJECT ||--o| CANONICAL_ENROLMENT : "enrolled (canonical only)"
PROJECT ||--o{ CANONICAL_OWNERSHIP : "per adopted scope"
PROJECT ||--o{ QUESTION_DEFINITION : "owns (canonical)"
PROJECT ||--o{ ANNOTATION_FORM : "owns (canonical)"
PROJECT ||--o{ SCREENING_PROFILE : "owns (canonical)"
PROJECT ||--o{ STAGE : "same stage ID; grants stay in Project"
PROJECT ||--o{ EXTERNAL_STEP_LEDGER : "reported steps"
PROJECT ||--o{ AI_SCREENING_MODEL_CONFIGURATION : "describes (XS1)"
PROJECT ||--o{ CONTRIBUTION_EXCLUSION : "admin decisions"
PROJECT ||--o{ PROJECT_DELETION_RECORD : "reversible deletion"
SYSTEMATIC_SEARCH ||--o{ EXTERNAL_STEP_LEDGER : "per search (optional)"
STAGE ||--|{ STAGE_SETTINGS_VERSION : "immutable versions"
STAGE_SETTINGS_VERSION ||--|| STAGE_STUDY_FILTER_VERSION : "embeds one"
STAGE_SETTINGS_VERSION }o--o{ ANNOTATION_FORM : "binds versions"
STAGE_SETTINGS_VERSION }o--o{ SCREENING_PROFILE : "binds versions"
STAGE_SETTINGS_VERSION }o--o| STAGE_ALLOCATION_REGIME : "by ID"
STAGE_SETTINGS_VERSION }o--o| BATCH_PLAN : "by ID"
ANNOTATION_FORM ||--o{ FORM_VERSION_ISSUE : "publishes through (one active)"
ANNOTATION_FORM ||--o{ DESIGN_DRAFT : "many drafts"
SCREENING_PROFILE ||--o{ ADJUDICATOR_ASSIGNMENT_VERSION : "who adjudicates"
SCREENING_PROFILE }o--o{ AI_SCREENING_MODEL_CONFIGURATION : "source policy pins a version"
STUDY ||--|{ STUDY_VERSION : "current pointer over immutable versions"
STUDY ||--o{ REVIEWER_STUDY_EVIDENCE : "per author scope (canonical)"
REVIEWER_STUDY_EVIDENCE ||--o{ FORM_SESSION : "one per form"
REVIEWER_STUDY_EVIDENCE ||--o{ ANNOTATION_HEAD : "one per context"
FORM_SESSION ||--o| SESSION_DRAFT : "draft with change log"
SESSION_DRAFT ||--o{ SESSION_DRAFT_CHANGE : "append-only"
FORM_SESSION ||--|{ FORM_SESSION_VERSION : "pins revisions"
STUDY ||--o{ CLAIM : "capacity claims (v2)"
STUDY ||--o{ STUDY_TARGET_OVERRIDE : "one per form, versioned"
STUDY ||--o{ SCREENING_OUTCOME : "one per profile (canonical)"
STUDY ||--o{ ADJUDICATION_TASK : "per profile and trigger (R4p)"
STUDY ||--o{ EXTERNAL_SCREENING_DECISION : "per source and profile (XS1)"
STUDY ||--o{ HISTORY_EVENT : "pool, release and start events (C20)"
STUDY ||--o{ RECONCILIATION_TASK : "one per form (R4a)"
RECONCILIATION_TASK ||--o| EDITOR_CLAIM : "one holder"
RECONCILIATION_TASK ||--o{ RECONCILIATION_ASSIGNMENT : "optional"
RECONCILIATION_TASK }o--o{ FORM_SESSION_VERSION : "pins candidates"
RECONCILIATION_TASK ||--o{ ACCEPTED_RESULT_VERSION : "immutable results"
ACCEPTED_RESULT_VERSION ||--|| GOLD_SNAPSHOT : "publishes one"
STUDY ||--o| STUDY_GOLD : "gold (canonical, reconciled)"
STUDY_GOLD ||--o{ GOLD_SNAPSHOT : "immutable"
STUDY_GOLD ||--o{ QUERY_WORK_ITEM : "per accepted version"
STUDY ||--o| ANIMAL_POPULATION : "created when C1 enables"
STUDY }o--o| PUBLICATION : "bibliographic identity (P1/P2)"
STUDY ||--o{ CITATION : "immutable records (home Study)"
STUDY_MERGE }o--|{ STUDY : "inputs, tombstoned at activation"
STUDY_MERGE ||--|| STUDY : "creates the consolidated Study"
STUDY_MERGE ||--o{ MERGE_CONFLICT_TASK : "resolved before commit"
STUDY_MERGE ||--o| STUDY_UNMERGE : "reversed by"
STUDY ||--o{ STUDY_LIFECYCLE_LEDGER : "retrieval and lifecycle"
STUDY ||--o{ EXPOSURE_LEDGER : "exposure, hints"
STAGE_SETTINGS_VERSION ||--o{ TRAINING_ATTEMPT : "training step"
PROJECT ||--o| PRISMA_PHASE_MAPPING : "required profiles"
PROJECT ||--o{ PRISMA_FLOW_SNAPSHOT : "frozen reports"
Resolution record¶
In the Where column, "patches (X)" names this drafter's change to X (contracts C1, C2 and C17; the decision register §2), now merged; the working patch file is not kept in the package.
| Finding | Category | Where | Note |
|---|---|---|---|
| DD-01 | Adopted (PROPOSAL) |
§1.1, §4.1, §9 | ReviewerStudyEvidence = (project, study, author scope); heads and revisions are entities; the F1a storage ADR decides documents within VB's four constraints |
| DD-02 | Corrected | §1.3, §10, §13 | ProjectCommitSequence deleted; Study version plus clock stamp; E25 settled at F1a (brief §1.2) |
| DD-03 | Adopted | §6.2, §13 | Event catalogue with the brief's three effect classes; C19 by the consistency drafter |
| DD-04 | Adopted | §6.1, §6.3; E59 | Command catalogue and hosting rule; PM capture capability as an R0 item |
| DD-05 | Adopted | §2 | Context map with relationship types; LegacyReviewDataAdapter named; shared kernels listed |
| DD-06 | Adopted (PROPOSAL, shape F1a, freeze F3) |
§4.2, §7.1 | Facets and CollectiveOutcomePolicy as single writer; the 25 September precedence rule is recorded as RECOVERED (research lines 818–823, verified by the consistency and versioning drafters) |
| DD-07 | Corrected | §4.3, §13; E63 | Task keyed by study × form; ReconciliationSession is a task entity; the compatibility class leaves the F4 decision list |
| DD-08 | Adopted (PROPOSAL) |
§4.7, §5, §9 | Merge as alias; AliasResolutionPolicy; presentation is D2-12. Superseded by the owner session (5 October 2026), see §4.7 and C21: one consolidated current Study with reversible unmerge |
| DD-09 | Adopted (PROPOSAL at F3) |
§4.4; E62 | One Stage aggregate; Active derived; Completed refuses settings publication except via an approved change request |
| DD-10 | Corrected (per brief §1.1) | §4.1, §4.5, §6.2 | Not batched materialisation of real versions: effects are derived on read and query-path projections are rewritten by an operation; "evaluate lazily on read" survives only as derivation for canonical readers; D2-01 |
| DD-11 | Adopted | §8 | Glossary with the renames; user-facing terms pending D3-03 |
| DD-12 | Adopted | §4.5, §4.6, §7.2, §13 | EntityTypeId minted at F1a; E14's identity part moves to F1a; O1 depends on it |
| DD-13 | Adopted | §1.7, §4.9, §5 | Per-document CanonicalScopes marker in the existing write filter, scope-aware per VB-07 |
| DD-14 | Adopted | §7.1; E60 | Policy catalogue, each a pure Core service with a fixture suite |
| DD-15 | Adopted | §4.1, §10 | Deterministic session IDs; the FormSession document is created on first autosave without touching Study |
| DD-16 | Adopted | §2, §5; A-30 | Project named as the Membership root, conformist to #3335; embedded jobs an explicit non-goal before R7; AC-M0-02 Project-contention line for the acceptance drafter |
| DD-17 | Adopted | §1.9, §5 | CanonicalSummary labelled a coexistence adapter retired at R7 |
| DD-18 | Adopted | §1.8, §4.2, §4.7, §4.9 | Ledger renames; one writer; ordering key |
| DD-19 | Adopted | §7.2; E61 | Value-object list with equality rules and shared-kernel ownership |
| DD-20 | Adopted | §4.8, §7.1 | Mapping stays project-level; StudyLifecyclePolicy in the outcome transaction |
| DD-21 | Adopted | §1.9; patches (C17) | Every read model declares its regime and freshness marker |
| DD-22 | Adopted | §11; E58 | Namespaces per context, internal default, fitness tests |
| DD-23 | Adopted | §6.1 | platform-architecture.md corrected in the F1a docs PR |
| DD-24 | Adopted | §4.6, §10 | Default population derived; aggregate only when C1 enables classification |
| DD-25 | Question | §1.5, §4.5 | D2-15 (system catalogue plus copy from administered projects); principle 5 amended on that basis. Owner session: D2-15 decided-amended (one application-wide catalogue with versioned copies, copy provenance and publication requests) |
| DD-26 | Adopted | §7.2; patches (C1/C2) | definitionOwner versus owningParent; "a candidate child never attaches to a reconciled parent" as a C1 conformance test |
| Q-D1 | Question | §4.5 | D2-15 |
| Q-D2 | Noted | §4.3 | RE4 already decides one task per study × form; no question needed (brief §1.9) |
| Q-D3 | Question | §4.7 | D2-12 (replaced by the owner session, 5 October 2026: one consolidated current Study, C21) |
| Q-D4 | Question | §8 | D3-03 ("Accepted answers (gold standard)") |
| Q-D5 | Question | §8 | D3-03 ("Screening result") |
| V2-15 | Corrected | §3 | StudyPdfCorrection and pmStudyPdfCorrection (verified through the generic repository); NumberOfStudies; roots at the Model root and inside ProjectAggregate/; ADR-020, M5b and outbox stores; writer inventory note |
| V2-16 | Corrected | §1.5, §4.5, §12 | System-scoped definitions allowed with their own authorization; R1a keeps copy provenance on the template, so no Project field before R0 |
| V2-17 | Corrected | §4.2, §4.4, §4.7, §5 | ScreeningOutcomeSummary on Study is FEAT-011's one screeningOutcomes[] array; lifecycle mode owned by the lifecycle part only; pmDedupAuditLedger versus FEAT-012's pmDedupAuditLog; pmDedupBatch listed |
| V2-18 | Corrected | §4.1, §4.2, §10 | Author scope in the session key through DefinitionOwner and separate reconciliation sessions; ProfileAdjudication versioned; conflict copy for the losing tab; ProfileSession as the screening container (PROPOSAL, fixed at F3/F5) |
| V2-20 | Corrected | §12 | Rows for M0, R2d, R3d, R4c, R5a, O2, R6, GA; Project in R2a; profile-version usage at F5 |
| V2-26 | Corrected | §13, §14 | Zero-or-one relations; ExternalStepLedger to Project and search; StudyAlias; claims; every gate listed |
| PH-16 | Corrected | §7.2; patches (register §2) | FEAT-001 D28, D49, D50-revised, D57 supersession rows; EntityPath element kinds |
| PH-27 | Question | §4.5 | D2-15 |
| PH-28 | Adopted (PROPOSAL at F5) |
§4.5, §13 | Keyword lists as a profile operational setting; project-level list legacy-only; no owner question needed |
| PH-30 | Adopted | §6.1, §13 | ADR-009 cited for the hosting rule; ADR-008 for every new timer |
| RT-11 | Adopted | §4.11, §5 | Claim contract v2; capacity claims on Study, editor claims on their aggregates |
| RT-15 | Adopted | §9 | Rows summarised here; the table itself is consistency-model §4 |
| RT §5.1 edits | Adopted | §3, §4.3, §4.11, §5, §9 | Presence and connection rows; task editor and requested-review claims; projection with per-reviewer markers; FormSessionId |
| NS-03 | Adopted | §4.10 | Generic Source, kind registry, one capture service |
| NS-18 | Corrected | §4.10, §5 | #3944 removed from the projection's readers; conversations refuse canonical scopes until R4a |
| NS-19 | Adopted | §2, §4.10 | Ownership split: capture, inbox, email, digests stay with the programme; StudyConversation to L6 at R4a; issues and checked PDFs to Study Management and PDF |
| NS §5.1 edits | Adopted | §3, §4.10, §9 | PR-only records listed; Source, ResolvedAtUtc (D3-23), NotificationFanOut; capture modes per operation in consistency-model §4 |
| AP-11 | Adopted | §4.4, §5 | Settings versions reference regime and batch plan by ID; embedded fields legacy-only |
| VB §3 item 1 | Adopted | §1.1, §10 | Collection list aligned with the storage blueprint; pmFormPublishOperation renamed pmFormVersionIssue |
Cross-cutting brief items reflected without a finding row: DC-02 and AP-01 (CanonicalSummary with
membership facts), MS-06 and MS-13 (FEAT-024 seam), VB-01, VB-02, VB-05, VB-09, VB-10, VB-13, VB-16,
VB-18, RT-10, RT-13, RT-14, RT-18 to RT-21, RT-24, RT-26, NS-01, NS-06, NS-08, NS-12, NS-20, NS-24,
AP-03, AP-05, AP-10, AP-14, AP-20, PH-05, PH-06, PH-07, PH-18, PH-25, PH-31.
Owner-session resolution record¶
Amendments from the nine specifications' §13 lists (5 October 2026), with where this page applies them. Planning only; implementation remains on hold.
| Source (§13 bullet) | Change | Where |
|---|---|---|
| RD §13 | Generated session versions replace "publication writes no evidence"; draft change log and decided form-owned timeout replace the lease and the D2-07 middle ground; AdditionalReviewRequest raises the effective target; placement table moves the target into the form version and the timeout and limit to the form; AnnotationForm gains standardTarget and ReconciliationPolicy; the D2-16 ceiling is deleted; Study gains state, currentVersionId, StudyVersion; new rows StudyVersion, StudyTargetOverride, DesignDraft, DesignDraftChange, SessionDraftChange; commands ApplyStudyTargetOverride, RequestAdditionalReviews, EditDesignDraft, CorrectPublication, generating ApplyIssuePolicy; glossary "Draft auto-saved"; F1a statuses |
Header; §4.1, §4.3, §4.4, §4.5, §4.7, §5, §6.3, §8, §13 |
| DM §13 | Header note; Identification context; §4.7 rows for Study state, StudyVersion, StudyMerge, MergeConflictTask, StudyUnmerge, CurrentEvidenceView; duplicate outcomes; merge and unmerge events and commands; new typed refusals; AliasResolutionPolicy and StudyAliasEntry removed; glossary; invariant; collections; P2 row; diagram |
Header; §2; §4.7; §6.2; §6.3; §7.1; §7.2; §8; §9; §10; §12; §14 |
| SP §13 | HistoryEvent replaces StudyPoolLedger with WorkFirstReleased and StagePool*; Stage row loses route policies and BL1 and gains filter, progression, exclusion-stop, continuation, route cap and browsing; placement table; pool-event writers, the sweep operation and new refusals; four new policies; glossary terms; collections and R3a row with filterInputs[] and stagePoolTracking[] |
§4.2, §4.4, §5, §6.2, §6.3, §7.1, §8, §10, §12 |
| RS §13 | resolutionState; ProfileAdjudication becomes AdjudicationTask; AdjudicatorAssignmentVersion; target-one tasks; AcceptedResultVersion; Verified removed; override grant; placement of blinding, VS1 and expiry; HintPolicy; AuthorityValue split; context-local aliases |
§4.2, §4.3, §4.4, §7.1, §7.2 |
| RI §13 | AIScreeningModelConfiguration, ExternalScreeningRun, ExternalScreeningDecision; outcome composition fields; WorkFirstReleased; report link replaced by prepared links on StudyVersion; search documentation versions and the protocol record; AuthorityValue split |
§2, §4.2, §4.7, §4.8, §5, §7.2 |
| BC §13 | Conversion records and firstCanonicalWriteAt; principle 7 (adapter retires at R7, originals stay stored) |
§1, §4.9, §5, §12 |
| TI §13 | TrainingStep, reference and policy versions; ClassificationRuleVersion; basis-keyed InferenceResult with history; training context with TrainingAttempt and TrainingAssessment; AuthorScope gains training; training lane row |
§2, §4.4, §4.5, §4.6, §4.12, §7.2, §12 |
| ACD §13 | Deletion lifecycle and Identity rows; Investigator rows; catalogue (CatalogueItem, CatalogueItemVersion, CataloguePublicationRequest, catalogueId); notification resolution, conversation retention, muted projects, NotificationContentPolicy; ContributionExclusion, ContributionExclusionLift, Project.deletionState, deletion and restoration records |
§1, §2, §2.1, §3, §4.5, §4.10, §4.13, §5 |
| UX §13 | Copy-deck terms (no direct domain-model bullet); applied to the glossary for consistency | §8 |
Open items carried from this page: D2-09 (T-OI-01) stays the one open owner decision; the
current evidence view design waits for its proof; the C20 freeze lists which event names are adapters
and which are new HistoryEvent types; storage for every owner-session row is a PROPOSAL for the
F1a storage ADR.