PRISMA Constraint Annotations for Phases 3-16¶
Purpose¶
This document annotates each implementation phase (3-16) with binding PRISMA constraints. Each phase's executor MUST read the relevant section before implementation. Release-level validation checklists MUST pass before deployment.
These constraints exist because data model decisions in any phase can silently break PRISMA 2020 flow diagram generation. A field added with a conflicting name, a lifecycle status that doubles as a screening outcome, or an Citation deletion during dedup -- any of these would make PRISMA reporting impossible or incorrect. By making constraints explicit, we prevent these mistakes at the point of implementation.
Normative language: "MUST" indicates an absolute requirement. "MUST NOT" indicates an absolute prohibition. "SHOULD" indicates a strong recommendation.
Cross-references: - prisma-flow-diagram-mapping.md -- PRISMA box-to-field mapping (17 boxes, 34 fields) - three-level-data-model.md -- Publication/Citation/Study entity specifications - deduplication-service-specification.md -- Dedup service interface, confidence model, enrichment rules - study-lifecycle-and-source-taxonomy.md -- 9-state lifecycle model, 6-value source taxonomy, PRISMA count derivation
How to Use This Document¶
- Before implementing a phase, read the corresponding section below. Each section lists MUST (required), MUST NOT (prohibited), and SHOULD (recommended) constraints.
- Cross-references point to the specific specification document and section that defines the requirement. Follow the link and read the referenced section before implementation.
- Release checklists (Section 4) are validation gates. Every item must be checked before the release deploys.
- If a phase's implementation conflicts with any MUST constraint, the implementation must be revised -- the constraint takes precedence.
- Constraint severity:
- MUST / MUST NOT: Violation would break PRISMA reporting or create irrecoverable data model conflicts
- SHOULD: Violation would not break correctness but would create technical debt or inconsistency
Per-Phase Constraint Annotations¶
Phase 3: Collection Infrastructure¶
PRISMA Impact: Low
Phase 3 creates pmAnnotationQuestion and pmQuestionSet collections with scope fields and optimistic concurrency. These collections are internal to annotation management and do not directly produce PRISMA data, but their naming and scope patterns should be forward-compatible.
Constraints:
- MUST: Scope fields on
pmAnnotationQuestionandpmQuestionSetsupport project-level filtering, ensuring future PRISMA report generation can aggregate annotation data by project - SHOULD: Use consistent naming patterns that align with other PRISMA-related entities (the
pmprefix convention, camelCase field names) - SHOULD: Optimistic concurrency pattern on Study (version field) should be designed to coexist with future
lifecycleStatus,screeningOutcomes[], andcitations[]fields
Cross-references: - three-level-data-model.md Section 1 (scope field convention)
Phase 4: Question Lifecycle¶
PRISMA Impact: None
Phase 4 implements draft question creation, stage activation, and AQ versioning. The question lifecycle is entirely internal to annotation management. No PRISMA constraints apply.
Constraints:
- None. Draft/Activated question lifecycle is internal to annotation management and does not affect PRISMA counting.
Phase 5: Annotation Form v2¶
PRISMA Impact: None
Phase 5 rebuilds the annotation form with signal forms, virtual scroll, and per-question auto-save. The form renders questions but does not affect PRISMA counting.
Constraints:
- None. The annotation form renders questions and collects answers but does not produce PRISMA-relevant data.
Phase 6: Question Management UI¶
PRISMA Impact: None
Phase 6 adds version history, version badges, and admin decision framework for question management. These are internal to QM.
Constraints:
- None. Version history and admin decisions for questions are internal to question management.
Phase 7: Release 1 Data Migration¶
PRISMA Impact: Medium (forward compatibility)
Phase 7 is the first migration that touches the Study and SystematicSearch entities. While Phase 7 does not populate PRISMA fields, it MUST ensure the schema is forward-compatible with fields that will be added in Phases 12-16.
Constraints:
- MUST: Add nullable
sourceTypefield (SearchSourceType?) toSystematicSearchentity -- this field will be populated in Phase 16 but the schema must accommodate it now - MUST: Add nullable
sourceNamefield (string?) toSystematicSearchentity -- free-text source name for PRISMA reporting - MUST: Ensure Study document schema is forward-compatible with future additions:
lifecycleStatus,screeningOutcomes[],duplicateGroupId,publicationId,citations[],fullTextStatus - MUST NOT: Add any field named
status,state, orlifecycleto Study that would conflict with the specifiedStudyLifecycleStatusenum (Active, Duplicate, PendingDuplicateReview, FullTextSought, FullTextNotRetrieved, Included, Merged, RemovedByAutomation, RemovedOther) - MUST NOT: Add any field to
SystematicSearchnamedtypeorcategorythat would conflict withSearchSourceType(Database, Register, Website, Organisation, CitationSearching, Other) - SHOULD: Verify no existing field names on Study conflict with planned PRISMA fields by running the validation query in Section 5
Cross-references: - study-lifecycle-and-source-taxonomy.md Sections 3, 5 (enum definitions) - three-level-data-model.md Section 3.3 (Study entity modifications)
Phase 8: Project Groups & Permissions¶
PRISMA Impact: Low
Phase 8 implements custom project groups and group-based stage permissions. The permission model indirectly supports PRISMA by enabling screener and reconciler role assignment for screening workflows that produce PRISMA data.
Constraints:
- MUST: Ensure
StageActivity.Reconcilepermission works for both annotation reconciliation AND screening reconciliation (screening reconciliation produces PRISMA exclusion reason data used in box 9) - SHOULD: Group-based permissions support future screener role assignment for PRISMA-tracked screening stages
- SHOULD: Permission group naming avoids terms that could be confused with PRISMA lifecycle terminology (e.g., do not name a group "Included" or "Excluded")
Cross-references: - study-lifecycle-and-source-taxonomy.md Section 2 (screening outcomes require reconciliation for PRISMA authority)
Phase 9: Reconciliation Model & Authority¶
PRISMA Impact: Low
Phase 9 creates the ReconciliationSession entity and authority determination rules. The reconciliation model itself does not produce PRISMA data, but its patterns MUST be compatible with the screening reconciliation model that does.
Constraints:
- MUST:
ReconciliationSessionmodel is compatible with theFinalScreeningOutcomepattern -- both use authority determination + versioned snapshots, so naming and structural patterns should align - MUST NOT: Authority determination rules overwrite or conflict with screening outcome data on Study -- annotation reconciliation writes to
ReconciliationSession, NOT toStudy.screeningOutcomes - MUST NOT: Add a study-level "reconciliation status" field that could be confused with
lifecycleStatus-- reconciliation status is per-session, not per-study - SHOULD: Use naming patterns consistent with the
ScreeningAuthorityenum values (CandidateAgreement,Reconciled) so that annotation and screening reconciliation share a coherent vocabulary
Cross-references: - study-lifecycle-and-source-taxonomy.md Section 2 (screening authority model, ScreeningAuthority enum)
Phase 10: Reconciliation Workflow & UI¶
PRISMA Impact: Low
Phase 10 implements the reconciliation workflow UI (pool assignment, blinded comparison, bulk approve, metrics, dashboard). The reconciliation workflow produces annotation authority but not PRISMA data.
Constraints:
- MUST NOT: Reconciliation outcomes modify
Study.screeningOutcomes-- those are set by screening reconciliation (Phase 15), not annotation reconciliation - SHOULD: Reconciliation dashboard could surface PRISMA-relevant counts (studies reconciled vs. pending) as a future enhancement, so data structures should not preclude this
Cross-references: - study-lifecycle-and-source-taxonomy.md Section 2 (distinction between annotation reconciliation and screening reconciliation)
Phase 11: Release 2 Data Migration¶
PRISMA Impact: Medium (must not conflict)
Phase 11 migrates study classification, reconciliation pools, and group data. While these do not produce PRISMA data directly, they MUST NOT introduce field names that conflict with the lifecycle and screening models that Phase 12-16 will implement.
Constraints:
- MUST NOT: Add any study classification field that uses names from the
StudyLifecycleStatusenum (Active, Duplicate, PendingDuplicateReview, FullTextSought, FullTextNotRetrieved, Included, Merged, RemovedByAutomation, RemovedOther) - MUST NOT: Add any field that stores screening outcomes in a format incompatible with the specified
ScreeningOutcomemodel ({ profileId, stageId, result, primaryExclusionReason, resolvedAt, authority }) - MUST: Any study classification added in this phase (e.g., reconciliation pool entry, auto-promote status) uses field names that are distinct from PRISMA lifecycle fields
- SHOULD: Study classification fields added in this phase should be designed to coexist with the future
lifecycleStatusfield without requiring migration renames
Cross-references: - study-lifecycle-and-source-taxonomy.md Sections 3, 7 (lifecycle status enum, field naming)
Phase 12: Deduplication Service¶
PRISMA Impact: HIGH (direct PRISMA data)
Phase 12 is the first phase that directly produces PRISMA data. It creates the Publication entity, Citation pipeline, and deduplication service. Every constraint in this section is critical for PRISMA box 3 accuracy.
Constraints:
- MUST: Create
pmPublicationcollection per three-level-data-model.md Section 2 specification (DOI unique sparse index, PMID unique sparse index) - MUST: Create
Citationentity with ALL fields specified in three-level-data-model.md Section 3.2, including:rawTitle,rawAuthors,rawDoi,rawPages,rawVolume,rawIssue,rawIsbn,rawAbstract,sourceType,sourceName,systematicSearchId,publicationId,importedAt - MUST: Implement dedup service interface per deduplication-service-specification.md Section 3 (
DeduplicationResult,DuplicateGroup,MatchSummarytypes) - MUST: Set
lifecycleStatus = Duplicateon auto-confirmed duplicates (high-confidence ASySD pairs) - MUST: Set
lifecycleStatus = PendingDuplicateReviewon probable duplicates (below auto-confirm threshold) - MUST: Preserve ALL Citations immutably -- never delete, never modify after creation (PRISMA requirement: per-source counting must remain derivable)
- MUST: Track duplicate count as
COUNT(Citations) - COUNT(distinct active Studies)for PRISMA box 3 (duplicatesfield) - MUST: Implement canonical enrichment per deduplication-service-specification.md Section 5 field-by-field priority rules (10 fields with MetadataProvenance tracking)
- MUST: Implement
DedupAuditLogfor all dedup decisions (auto and admin) per deduplication-service-specification.md Section 7 - MUST: Exclude Duplicate and Merged studies from all stage study pools (query-level enforcement, not deletion)
- MUST NOT: Delete Citations during dedup -- this breaks PRISMA per-source counting (box 2a, 2b)
- MUST NOT: Auto-merge studies that have review data (screening decisions or annotation sessions) -- admin MUST always decide for reviewed studies (system invariant)
Cross-references: - deduplication-service-specification.md -- Complete service specification (all sections) - three-level-data-model.md Sections 2, 3 (entity definitions) - prisma-flow-diagram-mapping.md Section 3.1, box 3 (duplicate count derivation)
Phase 13: Screening Profiles & Stage Settings¶
PRISMA Impact: HIGH (direct PRISMA data)
Phase 13 adds the screeningOutcomes[] array to the Study entity and creates screening profiles. This is the data structure that feeds PRISMA boxes 4-5 (title/abstract screening) and boxes 8-9 (full-text screening).
Constraints:
- MUST: Add
screeningOutcomes[]array to Study entity per study-lifecycle-and-source-taxonomy.md Section 2 specification - MUST: Each screening outcome records:
profileId,stageId,result(Included/Excluded),primaryExclusionReason,resolvedAt,authority(CandidateAgreement/Reconciled) - MUST: Screening profile result is per-profile (NOT a single Study-level screening status) -- each profile in the pipeline produces its own independent outcome
- MUST NOT: Add a single Study-level
screeningStatusfield -- this violates the multi-profile architecture that enables multi-stage PRISMA screening (boxes 4-5 vs. 8-9)
Cross-references: - study-lifecycle-and-source-taxonomy.md Sections 2, 7 (ScreeningOutcome model, edge cases)
Phase 14: Stage Filtering¶
PRISMA Impact: Medium
Phase 14 implements stage study pools with configurable filter rules. Pool membership tracking is essential for accurate "records screened" counts in PRISMA boxes 4 and 8.
Constraints:
- MUST: Stage study pools track pool entry for accurate "records screened" counting (PRISMA box 4:
dbr_screened= number of records that entered the title/abstract screening pool) - MUST: Pool membership is derivable from filter rules for count verification -- pool counts MUST match the result of re-running filter rules against the study collection
- SHOULD: Pool entry events are timestamped to enable temporal PRISMA reporting (when were records screened, not just how many)
Cross-references: - prisma-flow-diagram-mapping.md Section 3.2, boxes 4, 8 (screening count derivation)
Phase 15: Screening Annotations & Reconciliation¶
PRISMA Impact: HIGH (direct PRISMA data)
Phase 15 implements structured exclusion reasons and screening reconciliation. This is the phase that produces the data for PRISMA box 9 (reports excluded with reasons) and determines the authority of screening outcomes.
Constraints:
- MUST: Implement structured exclusion reasons with
primaryReasonfield -- this directly feeds PRISMA box 9 (dbr_excluded, broken down by exclusion reason category) - MUST:
FinalScreeningOutcomeuses theScreeningAuthorityenum (CandidateAgreement,Reconciled) to record how the screening decision was determined - MUST: Exclusion reasons are categorized and countable for PRISMA "Reports excluded with reasons" breakdown -- free-text-only reasons are not PRISMA-compatible
- MUST: Screening reconciliation produces the authoritative
screeningOutcomeon Study (the array entry'sauthorityfield is set toReconciledwhen reconciliation determines the outcome) - MUST NOT: Store exclusion reasons in a free-text-only format -- PRISMA requires categorized, countable exclusion reasons for the box 9 breakdown
Cross-references: - study-lifecycle-and-source-taxonomy.md Sections 2, 4 (ScreeningOutcome model, derivation rules for boxes 5, 9)
Phase 16: Release 3 Migration, Data Export & PRISMA¶
PRISMA Impact: CRITICAL (PRISMA implementation)
Phase 16 is the culmination of all PRISMA work. It backfills lifecycle statuses, migrates screening data, and implements the PRISMA flow diagram generation. Every prior constraint converges here.
Constraints:
- MUST: Backfill
lifecycleStatus = Activeon ALL existing studies (MIG-11) -- studies created before Phase 12 do not have lifecycle status; they default to Active - MUST: Migrate existing screening decisions to
screeningOutcomes[]format (MIG-12) -- legacy screening data stored in the old format must be converted to the per-profile ScreeningOutcome model - MUST: Populate
sourceTypeon SystematicSearches where determinable fromLibraryFileType(MIG-13), using the inference table from study-lifecycle-and-source-taxonomy.md Section 5.4 (at minimum: PubmedXml -> Database) - MUST: Migrate stage settings from legacy booleans to unified schema (MIG-14)
- MUST: Implement PRISMA flow diagram generation using ALL derivation rules from prisma-flow-diagram-mapping.md Sections 3.1-3.3
- MUST: Validate all 34 PRISMA fields are correctly derivable using the validation queries in this document (Section 5)
- MUST: Export PRISMA data as structured JSON/CSV (EXP-05)
- MUST: Export dedup report with canonical mappings and confidence scores (EXP-06)
- MUST NOT: Assume all SystematicSearches will have
sourceTypepopulated -- some will remain null for legacy data where the source type cannot be inferred; nullsourceTypemust be handled gracefully in PRISMA generation (counted separately or grouped with "Other")
Cross-references: - ALL specification documents in this directory -- Phase 16 must satisfy constraints from all four specifications
Release Validation Checklists¶
Release 1 Checklist¶
All items must pass before R1 deployment.
-
SystematicSearchentity has nullablesourceTypefield (SearchSourceType?) -
SystematicSearchentity has nullablesourceNamefield (string?) - Study document schema has NO fields that conflict with planned PRISMA additions:
lifecycleStatus,screeningOutcomes[],duplicateGroupId,publicationId,citations[],fullTextStatus - No fields on Study named
status,state, orlifecycle(reserved forStudyLifecycleStatus) - No fields on SystematicSearch named
typeorcategory(reserved forSearchSourceType) - Verify:
db.pmStudy.findOne({}, {lifecycleStatus: 1, screeningOutcomes: 1, duplicateGroupId: 1})returns null for all three fields (not yet populated)
Release 2 Checklist¶
All items must pass before R2 deployment.
- Study classification fields (if any added by Phase 11) do NOT use names from the
StudyLifecycleStatusenum (Active, Duplicate, PendingDuplicateReview, FullTextSought, FullTextNotRetrieved, Included, Merged, RemovedByAutomation, RemovedOther) -
ReconciliationSessiondata model does NOT overwriteStudy.screeningOutcomes - Authority patterns (
CandidateAgreement,Reconciled) are consistent between annotation reconciliation and screening reconciliation - No field on Study stores a single screening outcome that would conflict with per-profile
screeningOutcomes[] -
StageActivity.Reconcilepermission supports both annotation and screening reconciliation
Release 3 Checklist¶
All items must pass before R3 deployment. This is the most extensive checklist because Release 3 delivers the PRISMA implementation.
Lifecycle & Status:
- [ ] lifecycleStatus field on Study uses StudyLifecycleStatus enum values exactly as specified (Active=0, Duplicate=1, PendingDuplicateReview=2, FullTextSought=3, FullTextNotRetrieved=4, Included=5, Merged=6, RemovedByAutomation=7, RemovedOther=8)
- [ ] ALL existing studies have lifecycleStatus backfilled (default: Active)
- [ ] Duplicate and Merged studies are excluded from ALL stage study pools
Screening Outcomes:
- [ ] screeningOutcomes[] on Study matches ScreeningOutcome schema: { profileId, stageId, result, primaryExclusionReason, resolvedAt, authority }
- [ ] Existing screening decisions migrated to screeningOutcomes[] format
- [ ] FinalScreeningOutcome has structured exclusion reasons (NOT free-text only)
- [ ] Exclusion reasons groupable by primaryReason for PRISMA box 9 counts
Publication & Citation:
- [ ] pmPublication collection exists with DOI (unique sparse) and PMID (unique sparse) indexes
- [ ] Citation entity has ALL specified fields: rawTitle, rawAuthors, rawDoi, rawPages, rawVolume, rawIssue, rawIsbn, rawAbstract, sourceType, sourceName, systematicSearchId, publicationId, importedAt
- [ ] ALL Citations are immutable (verify no update operations on Citation fields)
- [ ] Duplicate count derivable: COUNT(citations) - COUNT(DISTINCT studies WHERE lifecycleStatus NOT IN (Duplicate, Merged))
Source Types:
- [ ] sourceType populated on SystematicSearches for new imports
- [ ] sourceType backfilled where determinable from LibraryFileType (at minimum: PubmedXml -> Database)
PRISMA Reporting: - [ ] PRISMA flow diagram generates correctly from: lifecycle counts + screening outcome aggregations + import record counts - [ ] All 34 PRISMA fields derivable via queries documented in prisma-flow-diagram-mapping.md Section 3 - [ ] Source column assignment works: Database/Register sources -> Column 1, all others -> Column 2
Audit & Compliance:
- [ ] DedupAuditLog captures all dedup decisions (auto and admin)
- [ ] Duplicate/Merged studies excluded from all stage study pools
- [ ] Dedup report exportable with canonical mappings and confidence scores
Validation Procedures¶
How to Validate Release 1 Checklist¶
1. Verify sourceType field exists on SystematicSearch:
// Field should exist and be null (not yet populated)
db.pmSystematicSearch.findOne({}, { sourceType: 1, sourceName: 1 })
// Expected: { _id: ..., sourceType: null, sourceName: null }
2. Verify no conflicting fields on Study:
// Check for field name conflicts with planned PRISMA additions
var study = db.pmStudy.findOne();
var conflictingFields = ['lifecycleStatus', 'screeningOutcomes', 'duplicateGroupId',
'publicationId', 'citations', 'fullTextStatus'];
conflictingFields.forEach(function(f) {
if (study.hasOwnProperty(f)) {
print('CONFLICT: Study already has field ' + f);
} else {
print('OK: ' + f + ' not present (expected)');
}
});
3. Verify no reserved field names on Study:
// These names are reserved for StudyLifecycleStatus
var reserved = ['status', 'state', 'lifecycle'];
var study = db.pmStudy.findOne();
reserved.forEach(function(f) {
if (study.hasOwnProperty(f)) {
print('CONFLICT: Study has reserved field name ' + f);
} else {
print('OK: ' + f + ' not present (expected)');
}
});
How to Validate Release 2 Checklist¶
1. Verify no lifecycle name conflicts:
// Check that no study classification field uses lifecycle enum names
var lifecycleNames = ['Active', 'Duplicate', 'PendingDuplicateReview', 'FullTextSought',
'FullTextNotRetrieved', 'Included', 'Merged', 'RemovedByAutomation', 'RemovedOther'];
// Grep codebase for these as field names (not enum references)
# Code search: verify no Study field uses lifecycle status names
grep -rn "lifecycleStatus\|screeningStatus\|studyStatus" \
src/libs/project-management/SyRF.ProjectManagement.Core/Model/Study.cs
2. Verify ReconciliationSession independence:
# Verify ReconciliationSession does NOT write to screeningOutcomes
grep -rn "screeningOutcomes" \
src/libs/project-management/SyRF.ProjectManagement.Core/Model/ReconciliationSession.cs \
src/services/project-management/
# Expected: no matches in reconciliation code
How to Validate Release 3 Checklist¶
1. Verify lifecycle status backfill:
// All studies should have lifecycleStatus
var total = db.pmStudy.countDocuments({});
var withStatus = db.pmStudy.countDocuments({ lifecycleStatus: { $exists: true } });
var withoutStatus = db.pmStudy.countDocuments({ lifecycleStatus: { $exists: false } });
print('Total: ' + total + ', With status: ' + withStatus + ', Without: ' + withoutStatus);
// Expected: withoutStatus = 0
2. Verify pmPublication collection and indexes:
// Check collection exists and has correct indexes
db.pmPublication.getIndexes().forEach(function(idx) {
print(JSON.stringify(idx.key) + ' unique:' + idx.unique + ' sparse:' + idx.sparse);
});
// Expected: doi_1 (unique, sparse), pmid_1 (unique, sparse)
3. Verify Citation immutability:
# No update operations should target Citation sub-fields
grep -rn "citations\.\$\[" \
src/libs/project-management/SyRF.ProjectManagement.Mongo.Data/Repositories/
# Expected: no matches (Citations are never updated after creation)
4. Verify PRISMA box derivation:
// Box 3: Duplicate count
var importCount = db.pmStudy.aggregate([
{ $unwind: "$citations" },
{ $count: "total" }
]).next().total;
var activeStudyCount = db.pmStudy.countDocuments({
lifecycleStatus: { $nin: [1, 6] } // Not Duplicate, not Merged
});
var duplicateCount = importCount - activeStudyCount;
print('Import records: ' + importCount + ', Active studies: ' + activeStudyCount +
', Duplicates (box 3): ' + duplicateCount);
5. Verify screening outcome structure:
// Verify screeningOutcomes array structure
db.pmStudy.findOne(
{ "screeningOutcomes.0": { $exists: true } },
{ "screeningOutcomes": 1 }
);
// Each entry should have: profileId, stageId, result, primaryExclusionReason, resolvedAt, authority
6. Verify exclusion reason categorization:
// Exclusion reasons must be groupable by primaryReason
db.pmStudy.aggregate([
{ $unwind: "$screeningOutcomes" },
{ $match: { "screeningOutcomes.result": "Excluded" } },
{ $group: { _id: "$screeningOutcomes.primaryExclusionReason", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
]);
// Expected: categorized reasons, not free-text
7. Verify source type backfill:
// Check sourceType population
var total = db.pmSystematicSearch.countDocuments({});
var withType = db.pmSystematicSearch.countDocuments({ sourceType: { $ne: null } });
var withoutType = db.pmSystematicSearch.countDocuments({ sourceType: null });
print('Total: ' + total + ', With sourceType: ' + withType + ', Without: ' + withoutType);
// Some null is acceptable (legacy data where type cannot be inferred)
8. Verify stage pool exclusion:
# Verify pool queries exclude Duplicate and Merged studies
grep -rn "lifecycleStatus" \
src/libs/project-management/SyRF.ProjectManagement.Mongo.Data/Repositories/
# Expected: pool queries filter by lifecycleStatus != Duplicate, != Merged
Summary: PRISMA Impact by Phase¶
| Phase | Release | PRISMA Impact | MUST Constraints | MUST NOT Constraints |
|---|---|---|---|---|
| 3 | R1 | Low | 1 | 0 |
| 4 | R1 | None | 0 | 0 |
| 5 | R1 | None | 0 | 0 |
| 6 | R1 | None | 0 | 0 |
| 7 | R1 | Medium | 2 | 2 |
| 8 | R2 | Low | 1 | 0 |
| 9 | R2 | Low | 1 | 2 |
| 10 | R2 | Low | 0 | 1 |
| 11 | R2 | Medium | 1 | 2 |
| 12 | R3 | HIGH | 12 | 2 |
| 13 | R3 | HIGH | 3 | 1 |
| 14 | R3 | Medium | 2 | 0 |
| 15 | R3 | HIGH | 4 | 1 |
| 16 | R3 | CRITICAL | 8 | 1 |
Total constraints: 35 MUST, 12 MUST NOT, 10 SHOULD
Document created: 2026-02-17 Part of: PRISMA 2020 Specification & Data Model Constraints