Specification: baseline conversion, recovery and legacy-writer retirement¶
Planning specification. Feature implementation remains on hold (Chris, 5 October 2026). The
owner decisions cited here are planning approval only. Brief approval and implementation
authorisation are separate, per gate (D1-04), and are still on hold. No migration, inventory of
production data, dry run against production, cutover, conversion wave, recovery execution or
legacy-writer retirement is authorised by this page. Nothing here says that work has started, that a
gate has passed or that anything is enabled in production. Storage shapes are marked PROPOSAL; the
F1a storage and naming ADRs fix them.
Sources. "Consolidation" is the owner-session consolidation, which wins over older text. "Register" is the 74-entry session register (R4 sections at its end). "Condensed" is the condensed packages (R4 package). "Stage filters" is the stage filter and step model. Package context: migration, adoption and rollback, consistency model §6, §7.7 and §13, versioning model §11, contracts C16, and the outcome-migration proposal.
1. Summary in plain English¶
SyRF will end up with one writable review engine. Every existing project, including completed and inactive ones, moves into the new data structures. Nothing stays on the old code for good, and the old writers are switched off only when every project has moved safely.
The move is a baseline conversion. It copies each project's existing set-up and review data into the new structures so that the project behaves exactly as it did before. The same studies are offered to the same people, the same answers and decisions are kept, the same exports come out and the same people have the same access. Conversion is not a redesign. It creates only the smallest set of new versioned structures (forms, screening profiles, steps, stage filters) needed to reproduce the old behaviour, and it never adds a new scientific rule because the new engine happens to support one.
Old SyRF did not record everything the new engine records. Where history is missing, the converted data says so with a named legacy-gap state such as "not recorded in legacy" or "current snapshot only". Conversion never invents a past version, a vote, a reviewer, a timestamp or a reconciliation result.
The order is fixed by Chris:
- Opt-in trials in staging on seeded and synthetic projects.
- Production pilots with projects whose owners opt in.
- Controlled conversion of every remaining project in scheduled waves, once parity is proven.
- Legacy-writer retirement as its own verified milestone that Chris approves separately.
Each project's conversion follows the same path: a read-only inventory and dry run, a review of the proposed mapping in the conversion wizard, an approved manifest, a shadow copy, a parity check, a fenced cutover and monitoring. The wizard shows exactly how each old stage's screening and annotation work maps to new steps, forms and profiles, what is created, what is reused, and where one reviewer has two overlapping contributions that must be resolved before they could count twice.
When a project cannot be converted faithfully, it is quarantined. Its evidence is kept, the blocker is recorded with a concrete remedy, and the project waits on the old path until the remedy lands. Conversion is never forced through by dropping data.
The safety boundary is the first canonical write. Until somebody writes new work in the new engine, a converted project can be switched back to the old path with nothing lost. After that, recovery moves forward inside the new engine and never flattens new work back into old records.
Later, inside the new engine, an admin can redesign the converted workflow with a separate wizard (for example, splitting one old stage into two steps). That is an ordinary versioned publication with impact previews. It is not a second migration.
This page also specifies disaster recovery (D2-13): restore a whole-database backup into an isolated environment, then recover forward with a manifest, never by overwriting live data.
2. Decisions covered¶
| ID | Decision in one line | Status | Section |
|---|---|---|---|
| R4 owner direction | One eventual writable engine; trials, pilots, then universal faithful baseline conversion of every project; optional later in-engine redesign | Decided | §1, §3.1, §10 |
| R4 amendment (explicit legacy activity mapping and adoption guidance) | The wizard maps each legacy stage's annotation and screening work to steps, forms and profiles, previews converging duplicates, and explains when to convert now or wait | Decided (amendment outside the register count) | §3.3, §4, §10.3 |
| R4 research finding | Permanent read-only archive adapter for completed projects | Replaced by the R4 owner direction | §14 |
| Q-05 | Existing outcome data converts inside the faithful baseline; untouched defaults stay ValueOrDefaultUnknown; dry run, manifest, staged copy, fenced cutover, rollback boundary |
Decided-amended (through R4) | §3.4, §4, §5 |
| Q-21 | Legacy screening maps to a reviewed legacy-compatible screening profile whose scientific meaning an admin confirms; no protocol is inferred | Decided-amended (through R4) | §3.4, §5 |
| D4-16 | Early limited adoption only for complete scopes with validated reader and writer coverage; reversible until the first canonical write | Decided-amended (through R4) | §5, §10.1 |
| Q-35 | No legacy reconciliation migration lane; the no-records premise is checked in every dry run and unexpected records stop that project's case | Removed (premise check retained) | §4.2, §5, §8 |
| D2-13 | Isolated point-in-time recovery with manifest-driven forward recovery, evidence checks and rehearsal | Brief item | §4.14, §8.4, §12 |
| Legacy-writer retirement (consolidation §5) | Retirement of legacy writers is its own verified, owner-approved milestone; originals and manifests are kept | Decided (direction) | §4.15, §10.1 |
Related decisions owned by other specifications (cited here, not restated):
| ID | Owner spec | What this spec relies on |
|---|---|---|
| D2-16 | Review domain and versioning | Replaced: the largest project is an acceptance case, never excluded for size |
| Q-24 | Stage pools, steps and history | Legacy stages have no steps; their actual behaviour is mapped to steps in the opt-in wizard |
| Q-29, D4-03 (R1) | Reconciliation and screening | Target-one handling; converted target-one forms use RS-R04a's conversion-only NoAcceptance (§12.4, ambiguity A1) |
| D3-06 | UX, devices and work discovery | Legacy screens are refreshed without behaviour change before conversion |
| D3-14 | UX, devices and work discovery | Missing staging seeds are added for trials; staging data is preserved where possible |
| D3-16 | Stage pools, steps and history | Capacity protection enabled per admitted pilot, with opt-in for legacy projects |
| S5 activation amendment | Training and inference | The inference beta is never switched on by baseline conversion |
| Q-06b, E1 | Reporting, imports and AI screening | Honest coverage disclosure for pre-conversion history in reports |
| O1 reversible project deletion | Access, communications and deletion | Deleted projects keep their deleted state through conversion (BC-R38) |
3. Concepts, entities and storage¶
3.1 Two operations that must not be confused¶
| Baseline conversion | Later redesign | |
|---|---|---|
| What it does | Moves a legacy project into the new structures with the same behaviour | Rearranges an already converted project inside the new engine |
| When | Trials, pilots, then universal waves | Any time after conversion, when an admin chooses |
| What it creates | The minimum versioned forms, profiles, stage settings, steps and filters that reproduce legacy behaviour, plus converted evidence snapshots | New form, profile and stage-settings versions through ordinary publication |
| Scientific choices | None. It keeps project-specific configuration and adds no new constraint | The admin's explicit choices, with impact previews and confirmation |
| History | Converted records carry manifest provenance; missing history is a legacy-gap state | Ordinary immutable version history on top of the baseline |
| Reversal | Routing rollback until the first canonical write (§4.9) | Guided rollback and republication, as for any publication |
Source: register "R4 owner direction", items 1 and 2; consolidation §5.
3.2 Legacy-gap states¶
Legacy SyRF overwrote values in place, never versioned questions and did not validate completion on the server. The baseline schema must say so explicitly. These states are domain states attached to the specific field or record that lacks the information. They are never answer values: a reviewer's Unknown, Not reported or Not applicable answer, and an unanswered new question, remain distinct from all of them (register "R4 owner direction").
State (PROPOSAL names, registry §4) |
Meaning | Example | Must not be confused with |
|---|---|---|---|
NotRecordedInLegacy |
Legacy never captured this kind of fact | Prior Save or Complete versions; screening reasons that were never collected; pool entries before tracking; step configuration before conversion | A reviewer answering Unknown; a blank optional question |
CurrentSnapshotOnly |
Only the latest value survives; earlier values were overwritten | A screening decision changed twice in legacy; an answer re-saved from another stage | A record with full version history |
UnknownLegacyAuthor |
The record exists but its author cannot be established | An answer whose investigator ID is missing or no longer resolves | An AI screening model source; a blinded alias |
UnknownLegacyTime |
The original time is missing or untrustworthy; the field stays null | A legacy record with no creation time | The conversion time, which is always recorded separately |
UnknownAuthoredUnderDefinition |
The question wording an answer was written under cannot be proven | The stored wording differs from the adopted v1 wording (AuthoredUnder = Unknown, versioning model §11) |
Verified(v1) wording |
ValueOrDefaultUnknown |
The stored value may be an untouched default | Outcome direction false, error type SD, average type mean, zero animals (Q-05) |
An explicit answer of zero or false |
LegacyCompletionUnvalidated |
Legacy marked the session Completed, but the server never validated it | Any legacy Completed session | A canonical Complete, which passed full validation |
E10's existing "membership-uncertain" label (an answer whose stage differs from its session's stage)
stays as a provenance flag on the converted revision. The F1a naming ADR decides whether it joins this
list under a registry name (PROPOSAL).
Where the states live (PROPOSAL). A small value object LegacyGap {state, reason, manifestId}
on the field it qualifies: historyCoverage on converted sessions and decisions; the C20 envelope's
coverage field on pool baseline events (SP §3.12);
authorKnown and nullable originalTime on converted revisions; authoredUnder on revisions;
valueCertainty on outcome observations; completionValidation on converted session snapshots.
Exports and manifests carry the same states as columns or labels.
3.3 Entities¶
Every entity below is a PROPOSAL name and shape unless it already exists in the package. Names not
in the brief's registry are flagged for the F1a naming ADR.
Conversion inventory¶
- What it is. A read-only survey of one project: counts and checksums per legacy collection, stages and their modes, question sets and overlaps, thresholds and targets, allocation regimes, grants, duplicate natural keys, invalid reviewer IDs, dangling questions and edges, missing timestamps, oversized documents, recent writer activity, legacy reconciled records (the Q-35 premise count) and the largest form's size.
- Identity. (project, inventory run). Each run is immutable.
- Versions and pointers. The manifest points to the inventory run it was built from.
- Mutability. Immutable once written.
- Storage (
PROPOSAL). ApmConversionInventorydocument per run, outside project data. In production it runs under a read-only database role and needs its own authorisation (migration §4 step 1). - What it is NOT. It is not a migration. It writes nothing to project data and never changes serving.
Conversion manifest and legacy activity mapping¶
- What it is. The approved, deterministic plan for converting one project: every legacy source record's target identity; the legacy activity mapping (for each legacy stage, which steps, forms and screening profile it becomes, which structures are created and which are reused, and how each existing session and decision maps); compatibility-profile labelling; target, capacity, timeout and blinding values; resolutions of duplicate same-reviewer contributions; unresolved records with their dispositions; the project's adoption findings; and the approver.
- Identity. (project, manifest lineage, version). A manifest version records the inventory checksums it was built on.
- Versions and pointers. Draft versions while the admin edits in the wizard; one approved version is the conversion input. Any change to the legacy source after approval invalidates it (AC-R6-01).
- Mutability. Drafts are editable with base-version checks; approved versions are immutable.
- Storage (
PROPOSAL).pmConversionManifestwith chunked item documents for large projects. - What it is NOT. It is not a redesign plan. It cannot choose a new protocol, merge stages automatically or drop evidence without a visible disposition.
Adoption finding¶
- What it is. One concrete, project-specific statement the wizard shows, with its consequence and remedy. For example: "Stages 2 and 3 share 14 questions about the same entity category. Until overlapping forms ship (R2d), they can convert only as one shared form; 6 reviewers have sessions in both stages."
- Identity. (manifest version, finding code, subject).
- Mutability. Immutable per manifest version; a later version carries forward or resolves it.
- Storage (
PROPOSAL). Inside the manifest. - What it is NOT. It is not a generic warning. Every finding names the affected stage, form, question, reviewer count or record count and a remedy (register "R4 amendment").
Baseline structures¶
- What they are. The minimum new definitions that reproduce legacy behaviour: question
identities with a v1 version each (counted as published, QD1); one annotation form per legacy stage
question set by default, whose v1 form version carries
FormVersion.standardTargetfrom the stage's effective legacy target; one legacy-compatible screening profile version reproducing the project's agreement maths and its tie behaviour; oneStageSettingsVersionper stage with the steps, dependencies, exclusion-stop and excluded-work settings that reproduce actual behaviour; aStageStudyFilterVersionper stage reproducing the legacy pool; aCapacityCaponly where legacy enforced the target as a cap; form-owned timeout and in-progress limits. - Identity and versions. Ordinary canonical identities, with v1 versions stamped with the manifest ID and the rule that produced them.
- Mutability. Immutable versions with mutable current pointers, as for any canonical definition.
- Storage. The ordinary canonical collections (domain model §4.4, §4.5).
- What they are NOT. They are not historical. Their effective time is the conversion time.
Configuration before conversion is
NotRecordedInLegacy. A one-stage-to-one-step mapping is never assumed to prove parity (register "R4 owner direction", item 1).
Converted evidence snapshots¶
- What they are. Each legacy annotation session becomes one form session with one converted
session version marked
CurrentSnapshotOnly, pinning converted answer revisions; each legacy answer becomes an answer head with one legacy revision; each legacy screening record becomes one decision under the legacy-compatible profile; legacy outcome data becomes series and observations under the legacy-compatible outcome schema (O1, Q-05). - Identity. Canonical IDs derived deterministically from (project, manifest lineage, legacy ID);
the legacy ID is kept through
LegacyIdAlias. - Versions and pointers. One converted version or revision each; later canonical work adds ordinary versions on top.
- Mutability. Immutable.
- Storage. The ordinary evidence collections (
pmFormSession,pmFormSessionVersion,pmAnnotationHead,pmAnnotationRevision, decision records), with the legacy-gap fields of §3.2. - What they are NOT. They are not invented versions. Prior Save or Complete versions, votes, adjudications and reconciliation results are never fabricated.
LegacyIdAlias (existing)¶
{projectId, legacyKind, legacyId, canonicalKind, canonicalId, manifestId}, unique on
(projectId, legacyKind, legacyId), append-only (versioning model §11).
It remaps notification-stack references (#3944 conversations, #3945 issues, inbox items) and exports
so that no saved link breaks (AC-R6-11).
Conversion attempt and operation record¶
- What it is. One attempt to convert one project (a pilot, or one item of a wave), run as an
ADR-020-shaped operation (
pmCanonicalOperation, kindbaselineConversion) with lease, generation, phase (shadowing,verifying,locking,committed,rolledBack,quarantined), cursor, counts and the manifest reference. - Identity. (project, attempt number).
- Mutability. Phase advances by compare-and-set; one active attempt per project through a unique partial index.
- What it is NOT. A failed or rolled-back attempt is never deleted. Its shadow records stay as
non-authoritative history, and a later attempt uses a new manifest version. The storage ADR fixes
identity derivation so that a retry neither collides with nor silently reuses an abandoned
attempt's records (
PROPOSAL).
Ownership markers and the recovery boundary¶
- Existing.
CanonicalScopesmarkers on Study and Project and thepmCanonicalOwnershipregistry (consistency model §6). Cutover stamps them through ADR-020's lock, verify, stamp and release protocol. - New (
PROPOSAL).firstCanonicalWriteAtandfirstCanonicalCommandIdon the project's ownership registry entry. The first canonical command that writes new evidence or configuration in a converted scope sets them in its own transaction, by compare-and-set on the registry entry. The routing-rollback command requires them to be null under the same compare-and-set. This makes the boundary in §4.8 exact. - What it is NOT. Enrolment and flags never change ownership (C16). Clearing a marker is only ever the routing-rollback command, before the first canonical write.
Conversion wave¶
- What it is. A scheduled batch of projects converted under one approval: the project list, the notice period, the execution window, the per-project status and the wave's exit evidence.
- Identity. Wave ID; immutable once approved, with a status history.
- Storage (
PROPOSAL).pmConversionWave. - What it is NOT. A wave never converts half of a project's authoritative scope. Each project is one item with its own all-or-nothing cutover.
Conversion parity report¶
- What it is. The semantic comparison between the legacy project and its shadow conversion: decisions and screening outcomes, answers, outcome data, current stage pools, offered work for sampled reviewers, permission-filtered API output per role, exports and statistics, plus timings.
- Identity. (attempt, run). Immutable.
- Storage (
PROPOSAL).pmConversionParityReport. - What it is NOT. It is not byte equality. Differences that the legacy-gap states explain are listed as expected; any other difference fails parity.
Conversion quarantine¶
- What it is. The record of a project that cannot be converted faithfully now: the blocker code, the evidence, the remedy, the owning lane, the review milestone and who is told.
- Identity. (project, quarantine ID); a status history (
open,remedied,retried,closed). - Storage (
PROPOSAL).pmConversionQuarantine. - What it is NOT. It is not a failure state for the project's users. The project keeps working on the legacy path (before cutover) or in read-only containment (after cutover; §8).
Conversion history events¶
Conversion writes structured events under C20 (HistoryEvent): BaselineConverted per project and
scope, with the manifest, attempt and operator; StagePoolBaselineMember for every Study in each
converted stage pool, with the matching filter version and clause evaluation, cause
BaselineConversion, effectiveAt equal to the conversion time and coverage =
BaselineAtTrackingStart, with earlier pool history labelled NotRecordedInLegacy because legacy
never recorded pool membership (SP §3.5.5, §3.12, §10.4); and ConversionRolledBack or
ConversionQuarantined where they happen. No earlier entry time or causal event is invented (stage
filters, "Explicit entry justification").
History discontinuity record and recovery manifest (D2-13)¶
- Existing. The history-discontinuity record per affected project (restore point, stamps lost, reason), reported by manifests and as-of requests (consistency model §13.1).
- New (
PROPOSAL).RecoveryManifest: the reviewed list of records to recreate in production from the isolated restore, each as a new command with provenance (source restore point, original record ID, recovery operator, approver). StoragepmRecoveryManifest.
Retirement readiness record¶
- What it is. The evidence pack for the legacy-writer retirement milestone: per-project conversion status (all converted), the empty consumer inventory, access, export and restore checks, retention approval and Chris's explicit approval.
- Storage (
PROPOSAL). A document in the decision register and a tracker row, not a database record.
3.4 What legacy data becomes¶
This table replaces the adoption-era mapping in migration §3 for the universal baseline. Every row is a faithful mapping, verified by parity.
| Legacy thing | Baseline target | Legacy-gap states used | Never inferred |
|---|---|---|---|
| Project annotation questions | Question identity plus a v1 version keeping original IDs; counted as published (QD1) | NotRecordedInLegacy for earlier wording |
Overwritten wording or options |
| System questions | Pinned SystemQuestionVersion per project system version |
None | That later code left the definition unchanged |
| Stage question set | One form per stage set by default, v1 version bound to that stage. A shared form across stages is an admin choice, shown with its duplicate preview | None | That two stages historically shared evidence |
| Overlapping question sets across stages | A shared form (admin choice) or overlapping forms once R2d ships; until R2d, a finding blocks separate forms that share an answerable question (A-19) | None | A silent merge |
Stage target (SessionCountTarget, override or inherited) |
FormVersion.standardTarget in the immutable v1 form version, materialised from the effective value at conversion |
None | That the screening threshold was meant as an annotation target |
| Converging stages with different targets | The admin chooses the shared form's standard target; the wizard shows the effect per Study | None | A guessed total |
EnforceAnnotationTarget |
A CapacityCap equal to the target where legacy enforced it; no cap otherwise |
None | A cap where legacy had none |
| Idle timeout, in-progress limit (stage-level) | Form-owned values (Q-28, D3-18); for converging stages the admin chooses, with the most restrictive as the suggested value | None | Stage-owned rules after conversion |
| Reconciliation blinding as configured in legacy | Form-owned blinding (profile-owned for screening); converging stages with different settings need an admin choice; blinded is the suggested value | None | A blinding setting legacy did not have |
| Stage mode (screening, annotation, combined) and excluded-work policy | One step per stage by default with the activities and dependencies that reproduce actual behaviour, including Allow or Stop for extra screening and the excluded-work setting (Q-24) | NotRecordedInLegacy for step settings before conversion |
Historical step settings |
| Stage filters, partitions and inclusion requirements | A StageStudyFilterVersion per stage whose clauses reproduce the legacy pool; pool parity is set equality at conversion; baseline members get StagePoolBaselineMember events with coverage BaselineAtTrackingStart |
NotRecordedInLegacy for pool history before conversion |
Earlier pool membership |
| Stage availability and completion state | The canonical lifecycle state and mode that reproduce availability; a closed or completed stage stays closed and is never reopened by conversion | NotRecordedInLegacy for status history |
Reopening to convert |
| Annotation sessions | One converted session version per session, CurrentSnapshotOnly; nullable times kept; legacy Completed becomes LegacyCompletionUnvalidated and counts as completed by default because legacy counted it (E10 admin choice) |
CurrentSnapshotOnly, LegacyCompletionUnvalidated, UnknownLegacyTime |
Prior Save or Complete versions; validity |
| Answers and parent and child trees | Answer heads with one legacy revision each; AuthoredUnder Verified(v1) or Unknown; conflicting duplicates become one Conflicted head |
UnknownAuthoredUnderDefinition, UnknownLegacyAuthor |
Context sharing from text similarity; "latest wins" |
| Same reviewer, same Study, converging routes | Previewed in the wizard and resolved under the provenance and conflict rules (BC-R14); counted once | CurrentSnapshotOnly |
A silent double count |
Screening records (project and screener) |
Decisions under the one legacy-compatible profile, current value only | CurrentSnapshotOnly; NotRecordedInLegacy for reasons and earlier decisions |
Earlier decisions, reasons, adjudications; a profile split by stage |
| Project agreement threshold and inclusion results | The legacy-compatible profile's collective rule reproducing the characterised legacy maths, with its tie policy set explicitly to ExtraReview with the bound legacy applied (RS-R50); outcomes recalculated and compared |
None | Separate historical profiles per array entry; an inferred tie default |
| Legacy reconciled answers or sessions | None expected (Q-35). The dry run counts them; any found stop that project's case (BC-R20) | n/a | Reconciliation authority |
| Single-reviewer studies on target-one forms | Converted candidate evidence only; the v1 form version carries targetOneHandling = NoAcceptance (RS-R04a), so conversion creates no accepted results and no reconciliation work; exports keep the label "single annotator, not accepted" (ambiguity A1) |
None | An accepted result; a reconciliation |
| Outcome data and time points | Legacy-compatible schema series and observations with stable paths (O1, Q-05, outcome-migration proposal) | ValueOrDefaultUnknown, CurrentSnapshotOnly |
Missing values from defaults; a majority direction |
| Permissions, groups, memberships | Preserved exactly, including disabled memberships and their history; owner-only actions enforced | None | Any broadened default |
| Reservations and claims | Translated under a coordinated lease transition at cutover; busy studies deferred, never force-released | None | Reviews, drafts or votes |
| Proportional allocation regime, if enabled | Blocker until AL1 is live (BC-R17) | n/a | Disabling allocation silently |
| Progressive batch plans, if present | Existing immutable membership kept; completion rebound to canonical requirements | None | Re-ordered membership |
| Search, import and PRISMA source data | Citations and source fields only where evidence exists; otherwise unknown with coverage labels | NotRecordedInLegacy |
A guessed source type; deduplication as a side effect |
| Notification-stack aggregates | Listed in the manifest; references remapped through LegacyIdAlias or marked unresolved |
None | Dangling references |
| Materialised statistics | Rebuilt under new family source versions; legacy basis labelled | None | Historical checkpoints for semantics that did not exist |
4. What loads and writes when¶
4.1 Summary table¶
| Action | Reads | Writes | Transaction boundary | Derived afterwards |
|---|---|---|---|---|
| Admin opens the conversion wizard | Project configuration, latest inventory, latest manifest draft, findings | Nothing | None | Nothing |
| Run inventory and dry run | Legacy project data under a read-only role | Inventory run; dry-run mapping preview; findings | Writes only to conversion records, one document per run | Wizard summary |
| Edit the mapping | Manifest draft and its base version | New manifest draft version | One compare-and-set on the draft | Findings recomputed for the draft |
| Approve the manifest | Draft, inventory checksums, current legacy checksums | Approved manifest version with approver and time | One write; refused if checksums changed | Wave or pilot becomes schedulable |
| Shadow copy | Legacy data at a recorded watermark | Non-authoritative canonical records with manifest provenance | Short idempotent batches, checkpointed | Nothing served |
| Verify parity | Legacy data and shadow records | Parity report | One document per run | Pass or fail; findings |
| Cutover | Shadow, legacy delta under locks, busy markers | Delta records, markers, registry, aliases, pool baseline events | ADR-020 per-batch locks, then one commit write | Statistics rebuilt; caches invalidated; notices |
| First canonical write | Registry entry | Sets firstCanonicalWriteAt with the command's own write |
Inside that command's transaction | Recovery boundary moves |
| Routing rollback | Registry entry (boundary null) | Markers cleared, attempt rolledBack, event |
One compare-and-set per marker batch, then the registry | Legacy serving resumes |
| Forward recovery or containment | Canonical records, recovery manifest | New commands with provenance | Ordinary canonical commands | Normal derivation |
| Quarantine | Failure evidence | Quarantine record; attempt phase | One write; locks released or led forward | Admin notice |
| Wave execution | Wave plan, per-project manifests | Per-project attempts | One operation per project | Wave exit evidence |
| Later redesign | Current baseline versions | New versions through publication | Ordinary publication protocol | Ordinary impact handling |
| D2-13 recovery | Isolated restore | Recovery manifest; new commands; discontinuity record | Production writes reopen only after the checker passes | Statistics rebuilt |
| Legacy-writer retirement | Inventory, conversion status, rehearsal evidence | Decision record; code removal | A release | Earlier images stop being rollback targets |
4.2 Inventory and dry run¶
- The operator (staging) or an authorised CAMARADES operator (production, once authorised) starts an inventory for one project.
- The job reads legacy collections under a read-only database role. Any write attempt fails (AC-O2-01r).
- It records counts, checksums and anomalies, and counts legacy reconciled sessions and answers for the Q-35 premise check.
- The dry run builds the default faithful mapping in memory and writes a dry-run preview and findings.
- Nothing in project data changes. The wizard reads the result.
4.3 Wizard review and manifest approval¶
- The project admin opens the wizard. It shows each legacy stage on the left and its proposed steps, forms, profile, filter, targets and settings on the right, with "created" and "reused" labels.
- For each stage the wizard lists how existing sessions, answers and decisions map, with counts.
- Where the admin chooses to converge two stages onto one shared form, the wizard lists every reviewer with work in both routes and asks for a resolution per conflict group (§9 example E2).
- The admin confirms the scientific meaning of the legacy-compatible screening profile (Q-21).
- Each edit is a new manifest draft version with a base-version check, so two admins never overwrite each other silently.
- Approval records the approver and time and pins the inventory checksums. If legacy data changes before cutover, the approval is invalid and the wizard says why.
4.4 Shadow copy and parity¶
- The operation copies legacy records into non-authoritative canonical records in short, checkpointed batches. Reruns create nothing new (AC-R6-03).
- FEAT-024's staged operation fence covers every statistics family during shadow and cutover (MS-17).
- Parity runs and writes its report. Statistics parity is automated for ProjectScreening and labelled manual for other families until per-family audits exist (#3845).
4.5 Cutover¶
- The operation takes its lease and raises the adoption fence.
- It locks Studies in batches through ADR-020. A Study that is busy (a legacy reservation, a canonical claim, an open task, an active draft or a bulk-update lock) is deferred and counted, never force-released.
- Under each lock it refreshes the delta since the shadow watermark and re-verifies it.
- It stamps
CanonicalScopeson each locked Study. Legacy writes to a stamped Study are refused with a retry message that keeps the reviewer's work. - A final pass retries deferred Studies until none remain or the stall limit is reached (§8).
- The commit write stamps the Project's markers, writes the registry entry, the
LegacyIdAliasrows that remain and theBaselineConvertedandStagePoolBaselineMemberevents, and records the operator. - Before the commit write, any failure unstamps and releases. After it, every interruption leads forward to release (migration §4 step 5).
- After commit: FEAT-024 families reset and rebuild under the new source versions; claims, presence records and scheduled messages are converted; admins and active reviewers are told.
4.6 Wave execution¶
- Chris approves the wave (project list and window). Each project's manifest must be approved (§6).
- Admins and active reviewers receive the wave notice during the notice period (§7).
- The wave runs one conversion operation per project, in a bounded number at a time (proposed, not approved). Each project commits or rolls back on its own.
- The wave closes with exit evidence: converted, quarantined, deferred and remaining projects.
4.7 Later redesign¶
The redesign wizard reads the current baseline versions and lets an admin, for example, split one step into two, move steps across stages, change form or profile arrangements or add a capability. Each change is a draft. Publishing it uses the ordinary publication protocol: impact preview, active-work warning, compatibility and target treatment, recheck at commit and retained history. No legacy data is read or written.
4.8 The first canonical write¶
The first canonical command that writes new evidence or configuration in a converted scope (a
reviewer's Save or Complete, a screening decision, a publication, a target override) sets
firstCanonicalWriteAt in its own transaction. Converting, rebuilding statistics and reading do not
count. From that moment the project's recovery mode changes from routing rollback to forward recovery.
4.9 Routing rollback (before the first canonical write)¶
- An authorised operator starts routing rollback with a reason.
- The command checks
firstCanonicalWriteAtis null by compare-and-set on the registry entry. If a canonical write won the race, rollback is refused and forward recovery applies. - It clears the Project and Study markers in batches and marks the attempt
rolledBack. - Legacy writers resume. Legacy data is exactly as it was at cutover, because conversion never wrote to it and legacy writers were refused afterwards.
- The converted records stay as non-authoritative history of the abandoned attempt.
4.10 Forward recovery and containment (after the first canonical write)¶
- New canonical writes for the scope stop (read-only containment); drafts are kept.
- Canonical data stays authoritative for what it holds. Canonical exports keep working.
- The fix is a set of new canonical commands with provenance, or a verified forward-recovery adapter.
- Writes reopen after the integrity checker passes.
- New work is never copied or flattened back into legacy records, and markers are never cleared.
4.11 Quarantine¶
- A failure at any step stops that project's attempt.
- Before the cutover commit, locks are released and markers cleared; the project keeps working on the legacy path.
- After the commit, the project goes to read-only containment (§4.10) until recovered forward.
- The quarantine record stores the blocker, evidence, remedy, owning lane and review milestone.
- The project admin sees the finding in the wizard; Chris sees it in the wave exit evidence.
5. Rules¶
| ID | Rule | Basis |
|---|---|---|
| BC-R01 | The target is one maintained writable review engine. Permanent parallel writable modes and permanent legacy archive adapters are not part of the plan. | Owner decision; consolidation §5; register "R4 owner direction" |
| BC-R02 | Every project converts, including completed, inactive and archived ones. The universal target includes projects that never opted into pilots. | Owner decision; consolidation §5 |
| BC-R03 | The sequence is synthetic and staging opt-in trials, then validated production pilots, then controlled scheduled conversion of every remaining project once coverage and behaviour parity are proven. | Owner decision; register "R4 owner direction" |
| BC-R04 | Conversion preserves existing functionality and workflow semantics. It forces no new scientific protocol choice and adds no workflow constraint merely because the new engine supports it. | Owner decision; consolidation §5 |
| BC-R05 | Conversion generates only the minimum versioned structures needed to reproduce existing behaviour, keeps original identities and provenance, and preserves the historical current state. | Owner decision; register "R4 owner direction", item 1 |
| BC-R06 | Completed and read-only state is preserved. Conversion never reopens a stage or project merely to convert storage. | Owner decision; register "R4 owner direction" |
| BC-R07 | Legacy completion semantics, conditional questions, combined activities and special project configurations are verified per project. A one-stage-to-one-step rule is never accepted as proof of parity. | Owner decision; register "R4 owner direction", item 1 |
| BC-R08 | Missing legacy information uses the legacy-gap states of §3.2. They stay distinct from Unknown, Not reported, Not applicable and unanswered answers. Nullable historical times stay null. | Owner decision; register "R4 owner direction" |
| BC-R09 | Conversion never fabricates versions, reviews, votes, timestamps, steps, adjudications or reconciliation results. | Owner decision; consolidation §5 |
| BC-R10 | Every converted record carries the actor or rule, source and target versions, baseline conversion time and manifest provenance. | Owner decision; register "R4 owner direction" |
| BC-R11 | The wizard maps each legacy stage's annotation activities, definitions and recorded work to annotation steps and generates the versioned forms needed. It shows what is created, what is reused and how old work maps. It never merely renames a stage or fabricates historical steps. | Owner decision; register "R4 amendment" |
| BC-R12 | Legacy screening activities and decisions map to screening steps and one legacy-compatible screening profile version based on verified old behaviour. An admin confirms its scientific meaning. No protocol, decision or reason is inferred. | Owner decision; Q-21; register "R4 amendment" |
| BC-R13 | Legacy stages have no steps. Their actual behaviour (mode, Allow or Stop, excluded-work policy, dependencies) maps to generated step settings effective from conversion; earlier step settings are NotRecordedInLegacy. |
Owner decision; Q-24; consolidation §3 |
| BC-R14 | Where several legacy routes converge on one shared form, the wizard previews each reviewer's duplicate contributions to the same Study. They are resolved before commit: agreeing compatible answers populate one converted session; conflicting answers become a Conflicted head for the reviewer to resolve, or the admin chooses; conflicting statuses need an admin choice (E10). The reviewer counts once. |
Owner decision; register "R4 amendment"; PROPOSAL for the resolution mechanics |
| BC-R15 | Merging stage question sets into one shared form is always an admin choice, never automatic. The default is one form per stage set. Separate forms that share an answerable question wait for R2d (A-19). | PROPOSAL; migration §3; A-19 |
| BC-R16 | The standard reviewer target becomes part of the immutable v1 form version (FormVersion.standardTarget). Converging stages with different targets need an admin choice. After conversion, the project screening threshold no longer moves annotation targets, and the wizard explains this change in how future edits work. |
Owner decision (target versions the form); AP-13 |
| BC-R17 | A project whose stage uses an enabled proportional allocation regime is blocked until AL1 is live. Conversion never disables allocation silently. | PROPOSAL; follows BC-R04; amends AC-R6-14 |
| BC-R18 | A choice not to map some work explains retained history access and any blocked or incomplete scope. It never drops evidence silently. | Owner decision; register "R4 amendment" |
| BC-R19 | Outcome data converts through the legacy-compatible schema with stable observation paths. Untouched defaults (false direction, SD, mean, zero animals) are ValueOrDefaultUnknown unless the dry run proves an explicit stored answer. Values consolidate only within one author's series for one measure. |
Owner decision; Q-05; outcome-migration proposal |
| BC-R20 | No legacy reconciliation lane is designed. Every dry run counts legacy reconciled records. If any appear, that project's conversion case stops, a quarantine records their provenance, and the treatment comes back to Chris. Authority is never fabricated. | Owner decision; Q-35 |
| BC-R21 | Conversion creates no accepted results and adds no reconciliation work that the legacy project did not offer. Converted target-one forms carry targetOneHandling = NoAcceptance (RS-R04a): no automatic result, no required reconciliation, and exports labelled "single annotator, not accepted". Only conversion sets this value. The admin may later move a form to AutoAccept or RequireHumanReconciliation by publishing a new form version (through the redesign wizard or ordinary publication), whose impact treatment (RS-R11) decides whether SingleAnnotator results are created. |
PROPOSAL; ambiguity A1; RS-R04a |
| BC-R22 | Readiness for any conversion phase requires representative inventories, every relevant reader and writer path accounted for, preserved UI behaviour, permissions, outcomes, pools, exports and statistics, acceptable large-project performance, a recovery rehearsal, trustworthy audit and complete manifests. | Owner decision; register "R4 owner direction" |
| BC-R23 | Pilot and limited scopes require complete validated reader and writer coverage. A scope is never split between legacy and canonical writers. Permitted partial boundaries for pilots are fixed in the brief; universal waves convert whole projects. | Owner decision; D4-16; C16 |
| BC-R24 | The largest project is an acceptance case. It is never excluded for size. If it fails a performance check, it is quarantined with a performance remedy. | Owner decision; D2-16 replaced; consolidation §6 |
| BC-R25 | Waves are idempotent and resumable, never leave a half-converted authoritative scope, coordinate active work and notify admins and reviewers. | Owner decision; register "R4 owner direction" |
| BC-R26 | A failed or unmappable project is stopped and quarantined without losing evidence, with the blocker recorded and remediated toward the universal target. Parity is never declared and a lossy conversion is never forced. | Owner decision; consolidation §5 |
| BC-R27 | Before the first canonical write, rollback restores routing to intact legacy data. After it, canonical-aware forward recovery preserves the new writes and never flattens history into legacy data. | Owner decision; consolidation §5 |
| BC-R28 | The first canonical write is recorded exactly (firstCanonicalWriteAt), and routing rollback checks it by compare-and-set. |
PROPOSAL |
| BC-R29 | Conversion never modifies or deletes legacy originals. Originals, manifests and aliases are retained after conversion and after retirement. | Owner decision; register "R4 research finding" and "R4 owner direction"; migration §1 |
| BC-R30 | The wizard explains when conversion is advisable now and when to wait, with concrete project-specific findings and remedies. During trials and pilots, waiting is a supported choice. During universal waves, waiting is a temporary recorded blocker with a review milestone. | Owner decision; register "R4 amendment" and "R4 owner direction" |
| BC-R31 | Later redesign is a separate versioned publication inside the new engine, with impact previews, active-work warnings, compatibility and target treatment, dependency safeguards and explicit admin confirmation. It repeats no storage migration. | Owner decision; consolidation §5 |
| BC-R32 | Baseline conversion never switches on optional beta capabilities (the inference beta, training admission rules, external AI screening imports). | Owner decision (S5 activation amendment); PROPOSAL for the other two |
| BC-R33 | Conversion writes the initial stage-pool baseline as structured StagePoolBaselineMember events with the matching filter justification and coverage BaselineAtTrackingStart. It invents no earlier entry time or cause; earlier pool history is NotRecordedInLegacy and reports disclose the coverage gap. |
Owner decision; stage filters "Explicit entry justification"; consolidation §3; SP §3.5.5 |
| BC-R34 | Disaster recovery restores a whole-database point-in-time backup into an isolated environment and recovers forward through a reviewed manifest. One live project's canonical data is never replaced directly from a backup. | Brief item D2-13; consolidation §7 |
| BC-R35 | After a restore, evidence links, current pointers, drafts and derived data are checked before writes reopen. Any genuine history discontinuity is recorded and disclosed in exports. | Brief item D2-13 |
| BC-R36 | Disaster recovery is separate from merge and unmerge reversal and from conversion rollback. Production recovery execution needs its own authorisation. | Brief item D2-13; register D2-13 context |
| BC-R37 | Legacy-writer retirement is its own verified milestone with explicit coverage, access, export and restore criteria and Chris's approval. No arbitrary date is set. Retirement deletes no immutable history or originals and needs no second active engine. | Owner decision; register "R4 research finding" and "R4 owner direction" |
| BC-R38 | A project in the reversible deleted state converts in that state, without notices to members, so that restoration stays possible after retirement. | PROPOSAL; follows O1 reversible deletion |
| BC-R39 | Manifest approval for project-specific choices (shared forms, duplicate resolutions, meaning confirmation, target choices) needs the project owner or a delegate. A wave approval may cover only default faithful mappings with no unresolved findings. | PROPOSAL; ambiguity A3 |
| BC-R40 | Production inventories are aggregate-only, read-only and separately authorised. They never copy project content into tooling outside SyRF. | Migration §4 step 1; PROPOSAL for the second sentence |
| BC-R41 | Each wave and each production pilot has its own execution approval. Approving this specification approves neither. | Owner decision; consolidation §5; AC-R6-06 |
6. Authorisation, blinding and provenance¶
Who does what (PROPOSAL until the brief maps it to the C10 capability catalogue):
| Action | Who | Notes |
|---|---|---|
| Run a staging trial | Testers and admins on staging seeds | Staging data preserved where possible (D3-14) |
| Opt a project into a production pilot | The project owner, with Chris's per-pilot approval | Enrolment is recorded on CanonicalEnrolment |
| Edit the mapping in the wizard | Project admins with the Design capability | Draft only |
| Approve a project manifest | Project owner or a migration delegate | Not the Design capability alone (outcome-migration proposal) |
| Approve a wave | Chris | Covers default mappings only (BC-R39) |
| Start inventory, shadow, cutover, routing rollback | Authorised CAMARADES operators under an approved pilot or wave | Every action audited with the real actor |
| Approve production recovery from a restore | Chris, per incident | D2-13 |
| Approve legacy-writer retirement | Chris | Separate milestone |
Blinding. Converted reconciliation and screening settings keep whatever blinding legacy applied;
blinded is the suggested value where converging stages differ. When an admin resolves a reviewer's
duplicate contributions, the admin sees only that one reviewer's own two contributions. If the admin
is also a candidate on that Study, the resolution is delegated to the original reviewer or another
admin (PROPOSAL, matching the merge-delegation model in
duplicate merge). Exposure of a candidate to another candidate's answers
never happens through the wizard.
Provenance. Every converted record names the manifest, the rule, the source legacy IDs, the conversion time and the operator, plus the original legacy author and time where known. Where they are unknown, the legacy-gap state says so. Conversion actions appear in the project's structured history (C20) and in the audit trail with the real actor.
7. Active-work impacts¶
| Moment | What the actor is warned about | Recheck at commit | Who is told afterwards |
|---|---|---|---|
| Before a trial or pilot cutover | Active reviewers (counts; names only with Monitor, D3-20), open legacy sessions, drafts, reservations, scheduled jobs, bulk-update locks, open conversations | ADR-020's lock phase refuses busy Studies; the delta is re-verified under the lock | Project admins; reviewers with active work |
| Wave notice period | The same impact summary per project, plus the window and what reviewers will see | Each project's cutover rechecks under its own locks | Admins of every project in the wave; reviewers with active work or recent activity (window proposed, not approved) |
| During the cutover window | Reviewers who save receive a typed "project upgrading, your work is kept" refusal and retry after release | n/a | n/a |
| Routing rollback | Who started work after cutover (none, by definition) | Boundary compare-and-set | Project admins |
| Quarantine after commit | Scope is read-only until recovered | n/a | Project admins and active reviewers |
Apply anyway is never offered by conversion. Conversion translates reservations and defers busy
Studies. It never releases a reservation or interrupts work to make progress (PROPOSAL; the general
Apply anyway rules are in access, communications and deletion §7).
Notices. Wave and pilot notices use the "Project changes" kinds (adoption cutover, pilot admitted, removed or made read-only) only where notification delivery has passed G-NOTIF (D3-21). Otherwise the project banner and "My work" carry them. Exact notice and override rules belong in the brief (register "R4 owner direction").
8. Failure and recovery¶
8.1 Failure taxonomy¶
| Failure | When | Handling | Project state after | Users see |
|---|---|---|---|---|
| Inventory finds unexpected legacy reconciled records | Dry run | Stop the case; quarantine; treatment to Chris (Q-35) | Legacy | Finding in the wizard |
| Unmappable value (an option value with no option, a dangling question, an invalid reviewer ID) | Dry run | Visible disposition in the manifest or quarantine | Legacy | Finding with the record count and remedy |
| Overlapping answerable questions before R2d | Dry run | Finding; shared-form choice or wait for R2d | Legacy | Finding |
| Enabled proportional allocation before AL1 | Dry run | Blocker (BC-R17) | Legacy | Finding |
| Parity difference not explained by a legacy-gap state | Verify | Fail parity; quarantine with the diff | Legacy | Finding with the diff summary |
| Performance check fails (including the largest project) | Verify | Quarantine with a performance remedy (BC-R24) | Legacy | Finding |
| Legacy source changed after approval | Before cutover | Manifest invalid; re-approve | Legacy | "Project changed since approval" |
| Busy Studies stay busy past the stall limit | Cutover | Unstamp and release; reschedule | Legacy | Admin notice; drafts untouched |
| Crash before the commit write | Cutover | Lease expiry, takeover, unstamp and release | Legacy | Typed retry messages during the window |
| Crash after the commit write | Cutover | Takeover leads forward to release | Converted | Brief pause |
| Mismatch found after cutover, no canonical write yet | Monitoring | Routing rollback (§4.9) | Legacy | Admin notice |
| Mismatch found after the first canonical write | Monitoring | Read-only containment and forward recovery (§4.10) | Converted, contained | Read-only notice; drafts kept |
| Whole-database data loss | Any time | D2-13 recovery (§8.4) | Per recovery | Discontinuity notice on affected projects and exports |
8.2 Containment¶
Read-only containment keeps every converted record readable and exportable, refuses new canonical commands for the scope with a typed message that keeps drafts, and never hands the scope back to legacy writers. Configuration changes and enrolment changes never clear markers (C16).
8.3 Remediation toward the universal target¶
A quarantine is closed only by remedying the blocker (a delivered capability, a resolved mapping, a performance fix, an owner decision) and converting successfully. The review milestone keeps a blocked project visible on the tracker. No quarantine ends by dropping data.
8.4 Isolated point-in-time recovery (D2-13)¶
- Restore a whole-database point-in-time backup into an isolated database. Live projects keep running or are contained, depending on the incident.
- Compare the isolated restore with production for the affected projects and build a reviewed recovery manifest: which records to recreate, from which restore point, and why.
- Recover forward by issuing new canonical commands with provenance (source restore point, original record ID, recovery operator and approver). Nothing in production is overwritten, and no selective per-project restore of canonical data happens.
- Record a history-discontinuity record per affected project (restore point, stamps lost, reason). Manifests, as-of requests and exports disclose it; as-of exports already issued at later watermarks are flagged.
- Reconcile scheduled state in SQL Server (MassTransit scheduled messages, Quartz) from MongoDB state, because it does not rewind with Mongo.
- Check evidence links, current pointers, drafts, command-bearing records, the canonical summary, markers and the registry with the integrity checker. Writes reopen only when it passes.
- Rebuild FEAT-024 families and other derived stores.
- Commands committed after the restore point and not recovered are lost; a client retrying one either
succeeds against the restored base or gets
StaleBase.
The specification and a rehearsal on an authorised non-production copy are required before the first production pilot (E55). Production recovery execution needs Chris's authorisation per incident.
9. User flows and examples¶
The people and projects below are illustrative. Francesca's largest project is real context from the consolidation; its figures beyond "2,023 questions" are not asserted here.
E1. Priya's staging trial (loading, pending, completed)¶
Priya administers the staging seed project "Stroke models". It has two stages: Stage 1 screens titles and abstracts with a two-reviewer agreement threshold, and Stage 2 is a combined full-text screening and annotation stage with 40 questions and a target of two.
- Priya opens the wizard. It shows a loading state while it reads the latest inventory, then the mapping.
- Stage 1 maps to one screening step using the legacy-compatible profile "Legacy project screening", whose collective rule reproduces the two-reviewer threshold. The wizard labels the profile "created". Priya confirms its meaning as title and abstract screening.
- Stage 2 maps to one combined step that uses the same profile (legacy screening is project-level) and a new form "Stage 2 questions" v1 with standard target two. Legacy allowed extra screening after sufficiency, so the step uses Allow. The wizard says the new-step default would be Stop and that the baseline keeps Allow to match legacy.
- The dry run maps 1,850 sessions; 1,612 legacy Completed sessions become
LegacyCompletionUnvalidatedand count as completed, as they did in legacy. - Priya approves the manifest. The status is pending until the operator runs shadow, parity and cutover. Parity passes, cutover commits, and the wizard shows completed with the parity report.
E2. Converging routes and a duplicate contribution (conflict)¶
In Ben's project, Stages A and B use identical question sets. The admin, Omar, chooses one shared form. The wizard lists 6 reviewers with sessions in both stages. Ben's sessions on Study 42: Stage A Completed with "Species: rat"; Stage B saved incomplete with "Species: mouse".
- The wizard shows both side by side in a reconciliation-style view, with the routes and legacy times
(
UnknownLegacyTimewhere missing). - Agreeing answers fill the resolution controls. "Species" conflicts. The statuses also differ (Completed and saved incomplete), so the resolver must choose the converted status as well.
- Omar can resolve it himself or delegate it to Ben. He delegates. Ben's task names the conversion and
the exact inputs. Until Ben resolves it the group stays visibly pending, and the manifest
cannot be approved with it unresolved. Omar has one alternative: convert "Species" as a
Conflictedhead holding both values, which Ben fixes after conversion. The status choice is still needed before approval. - Ben's converted session counts once toward the shared target. The actual resolver is recorded.
E3. A completed 2019 review in a universal wave (historical, completed)¶
Dr Lewis's 2019 project has been inactive for four years. Its two stages are complete.
- The wave notice reaches Dr Lewis as project owner. No reviewer has active work, so reviewers get no notice.
- Conversion uses default faithful mappings only. The screening profile is labelled "Legacy project screening (meaning not confirmed)" and has no PRISMA phase until someone confirms it (ambiguity A2).
- Both stages stay completed in manual mode. Nothing reopens.
- The old export formats produce the same content, with legacy-gap labels in designated columns. The project shows a historical note: "Converted on [conversion date]. Review history before that date is current snapshot only; stage pool history before it was not recorded."
E4. Francesca's largest project (failure, then remedy)¶
Francesca's project has a 2,023-question form. It is an acceptance case.
- The trial conversion on an authorised copy passes data parity but the post-conversion check of opening the form on a phone exceeds the agreed budget (budget proposed in the brief, not approved).
- The attempt is quarantined with the finding "Large-form phone load above budget" and the remedy "virtual scrolling and diff autosave performance work (UX lane)". The project keeps working on the legacy path. This is a failure state for the attempt, not for the project.
- After the remedy ships, the retry passes and the project converts. It was never excluded.
E5. Unexpected reconciliation records (unavailable)¶
The dry run for project "Sepsis 2022" counts 3 legacy reconciled sessions. The Q-35 premise does not hold for this project.
- The case stops. The wizard shows "Conversion unavailable: 3 legacy reconciled sessions found. Their treatment needs an owner decision." with the record IDs for authorised admins.
- The quarantine record goes to Chris through the wave exit evidence. Nothing is converted, and nothing is labelled as an accepted result.
E6. Rollback before and after the first canonical write¶
- Before. The morning after a pilot cutover, Priya notices an export column mismatch. Nobody has
saved anything yet. The operator runs routing rollback. The compare-and-set confirms
firstCanonicalWriteAtis null, markers are cleared, and the project is back on the legacy path with nothing lost. - After. In another pilot the same mismatch is found after a reviewer saved a session. Rollback is refused. The scope goes read-only; drafts are kept; a forward fix is issued as new commands; writes reopen after the checker passes.
E7. Accidental data loss (D2-13)¶
A faulty operator script corrupts records in several projects at 10:00.
- Writes for affected projects are contained.
- The 09:55 point-in-time backup is restored into an isolated database.
- The recovery manifest lists the records to recreate. Chris approves it.
- New commands recreate them with provenance. Each affected project gets a discontinuity record, and its exports say "history discontinuity at 09:55 to 10:20 on this date".
- The checker passes and writes reopen.
E8. Later redesign of a converted project (pending, completed)¶
A year after conversion, Priya wants Stage 2 split into "Full-text screening" then "Annotation", with annotation depending on the reviewer's Include. She uses the redesign wizard. The draft shows the impact: 37 reviewers with saved work, 4 active drafts, no change to existing decisions or sessions. She publishes; the new stage-settings version applies from that moment; history keeps the baseline.
E9. An empty project¶
A project with no studies and no review data converts in seconds. The wizard shows an empty summary: "No review data to convert. Your stages and questions will be set up in the new structures."
10. Rollout and adoption¶
10.1 Phases¶
| Phase | What happens | Lands in (PROPOSAL for the rollout drafter) |
Entry gate |
|---|---|---|---|
| 0. Foundations | Writer and reader inventory (AC-M0-03); CanonicalScopes markers and the composite write guard (R0); integrity checker (R2a); D2-13 rehearsal |
M0, R0, R2a | F1a |
| 1. Staging trials | Opt-in conversion of seeded and synthetic projects as each scope becomes complete: annotation-only after R2a and R2b; combined after R3a; profiles after R3b; reconciled scopes after R4a and R4p; extraction after O1 and O2; pools and history with R3a; exports with R5a | Each release's T1 rehearsal | The release's own gate |
| 2. Production pilots | Owner opt-in projects, each with its own approval; partial scopes only where complete (BC-R23) | Per pilot | G-ADOPT for the pilot; D2-13 rehearsal passed |
| 3. Universal waves | Scheduled conversion of every remaining project, including completed, inactive and deleted ones | R6, reframed as universal baseline conversion waves | G-ADOPT per wave; parity proven on pilots; Chris's wave approval |
| 4. Legacy-writer retirement | Remove legacy writers and adapters after every project converted | R7, its own verified milestone | G-RETIRE; Chris's approval |
| Later. Redesign wizard | In-engine rearrangement of baseline workflows | After R3a and R2c (publication); scheduled by the rollout drafter | Ordinary release gate |
Flags: conversion is gated per project by CanonicalEnrolment and ownership markers, not by
environment flags. The wizard and wave tooling sit behind default-off flags until their release gates
pass (flag decision required by the repository rules).
10.2 Dependencies¶
M0 inventory; R0 floor and markers; R2a integrity checker and legacy capture; R2b shared sessions; R2d overlapping forms (for projects with overlapping question sets); R3a steps, routing and pool history; R3b profiles; R4a and R4p only where legacy reconciliation exists (expected none, Q-35); O1 and O2 for extraction; R5a as-of exports; AL1 for projects with allocation; X-CLAIMS for capacity behaviour in production (D3-16); FEAT-024 rebuild and parity tooling (#3845); the deletion lifecycle (X-DEL) for deleted projects.
10.3 Adoption guidance: convert now or wait¶
The wizard recommends conversion when every row below is green for the selected scope, and gives the specific remedy otherwise (register "R4 amendment").
| Check | Recommend converting now when | Advise waiting when (finding example) | Remedy |
|---|---|---|---|
| Capability delivered | Every activity the project uses is delivered and validated | "Stage 3 uses proportional allocation; AL1 is not live" | Wait for AL1 |
| Faithful mapping | Every stage maps with no unresolved semantics | "Stage 2 conditional question Q17 has 4 option values with no option" | Admin maps or dispositions the values |
| Data preservation | Dry-run accounts for every record | "212 answers reference a deleted question" | Disposition in the manifest |
| Eligibility behaviour | Pool and offered-work parity pass | "Pool parity differs for 9 Studies in Stage 2" | Investigate filter mapping |
| Overlaps | No overlapping answerable questions, or a shared-form choice is made | "Stages 2 and 3 share an entity category" | Choose a shared form or wait for R2d |
| Performance | Large-form and project checks pass | "Phone form load above budget" | Performance remedy (E4) |
| Publication and target impacts | Targets and converging choices resolved | "Stages A and B targets differ (2 and 3)" | Admin chooses the shared target |
| Active work | Disruption can be managed | "41 active drafts during term time" | Schedule a quieter window |
| Rollback boundary | Boundary and recovery path are clear | n/a | n/a |
| Premise checks | No legacy reconciled records | "3 legacy reconciled sessions" | Owner decision (E5) |
During trials and pilots, "wait" is a supported choice. During universal waves it becomes a temporary quarantine with a review milestone (BC-R30).
11. Acceptance evidence¶
| ID | Evidence | Method | Amends |
|---|---|---|---|
| BC-AE01 | A dry run on a fixture runs under a read-only database role; any write attempt fails; it produces counts, checksums, findings and the Q-35 premise count. | Integration | AC-O2-01r (generalised to every scope) |
| BC-AE02 | For each FX-LEGACY fixture, every legacy record maps once or has a visible disposition; reruns create nothing new. | Integration | AC-R6-03 |
| BC-AE03 | Every converted record carries manifest ID, rule, source IDs, conversion time and operator; known legacy author and time are kept; unknown ones carry UnknownLegacyAuthor or UnknownLegacyTime with null values. |
Integration; inspection | AC-R6-06 |
| BC-AE04 | Each legacy-gap state appears on the right field in fixtures and in exports and manifests, and none is confused with Unknown, Not reported, Not applicable or unanswered values. | Integration | AC-R6-09 |
| BC-AE05 | Untouched outcome defaults convert as ValueOrDefaultUnknown unless the dry run proves an explicit answer. |
Integration | AC-O2-02; C14-T04 |
| BC-AE06 | The wizard shows, per legacy stage, the generated steps, forms, profile, filter, targets and settings with created and reused labels, and the mapping of existing sessions and decisions with counts. | E2E; user test with the tester panel | New |
| BC-AE07 | Converging two stages onto one shared form lists every reviewer with work in both routes; the manifest cannot be approved with an unresolved group; after conversion each reviewer counts once and the resolver is recorded. | Integration; E2E | New |
| BC-AE08 | The legacy-compatible profile reproduces the characterised legacy inclusion maths on fixtures; the admin's meaning confirmation is recorded; an unconfirmed profile carries no PRISMA phase. | Integration | AC-R6-15 |
| BC-AE09 | The converted form version holds the effective legacy target as FormVersion.standardTarget; a later threshold change does not move it; the wizard shows this change. |
Integration | AC-R6-14 |
| BC-AE10 | A fixture with enabled proportional allocation produces a blocker finding and no conversion before AL1. | Integration | AC-R6-14 |
| BC-AE11 | A fixture with legacy reconciled records stops the case and writes a quarantine; no accepted result or reconciliation authority is created. | Integration | Replaces AC-R4a-12 and C9-T14 |
| BC-AE12 | Conversion creates no accepted results and offers no reconciliation work that the legacy fixture did not offer. | Integration | Replaces AC-R6-08 |
| BC-AE13 | Semantic parity passes per fixture: decisions and outcomes, answers, outcome data, current stage pools (set equality), offered work for scripted reviewers, permission-filtered API output per role, exports and statistics (automated for ProjectScreening, labelled manual elsewhere until #3845). | Integration; E2E | AC-R6-04 |
| BC-AE14 | Behaviour journeys on a converted fixture match the legacy fixture: the same Studies are offered to the same reviewer, completion and eligibility behave the same, and excluded-work and Allow or Stop behaviour match. | E2E | New |
| BC-AE15 | Completed and closed stages stay closed after conversion; no stage reopens. | Integration | New |
| BC-AE16 | The largest-project fixture (and, under authorisation, the real largest project on a copy) converts within a measured budget, and post-conversion form load, save and export meet the UX budgets on phone, tablet and desktop. Budgets are proposed in the brief, not approved. | Benchmark on Bramble; user test | Replaces AC-R2a-22's exclusion premise |
| BC-AE17 | Cutover is all-or-nothing through ADR-020's protocol; busy Studies are deferred and never force-released; legacy writes during the window are refused with a draft-keeping retry. | Integration with failure injection | AC-R6-05 |
| BC-AE18 | Induced failure at each step (copy, verify, lock, delta, stamp, release) leaves the project either fully legacy (before commit) or fully converted (after commit). | Integration with failure injection | Migration §1 principle 7 |
| BC-AE19 | Routing rollback succeeds when firstCanonicalWriteAt is null and is refused when a canonical write wins the race, under forced interleaving. |
Integration | New |
| BC-AE20 | After the first canonical write, rollback produces read-only containment; no canonical write is copied into legacy records; markers are never cleared. | Integration | Migration §5 |
| BC-AE21 | A quarantined project keeps working on the legacy path (before commit) or read-only (after commit) with no evidence lost; its record names blocker, evidence, remedy, lane and review milestone. | Integration; inspection | New |
| BC-AE22 | Conversion writes StagePoolBaselineMember events for every Study in each converted pool with filter justification and conversion-time effectiveAt; reports disclose the pre-conversion coverage gap. |
Integration | New |
| BC-AE23 | LegacyIdAlias remaps conversations, issues and inbox items; after cutover no saved link breaks. |
Integration; E2E | AC-R6-11 |
| BC-AE24 | A wave run twice converts nothing twice; a crash mid-wave resumes; each project commits or rolls back on its own. | Integration | New |
| BC-AE25 | A deleted project fixture converts in its deleted state with no member notices, and restoration after conversion works. | Integration | New |
| BC-AE26 | Conversion leaves the inference beta, training admission rules and external AI screening imports off. | Integration | New |
| BC-AE27 | D2-13 rehearsal on an authorised copy: whole-database restore into an isolated database, recovery manifest, forward recovery by new commands, discontinuity records, scheduled-state reconciliation, integrity checker green before writes reopen. | Rehearsal; inspection | AC-R2a-29; AC-R7-02 |
| BC-AE28 | Legacy originals and manifests remain byte-identical after conversion and after a retirement rehearsal. | Inspection; checksum comparison | AC-R7-03 |
| BC-AE29 | The retirement readiness record shows every project converted, an empty consumer inventory, passing access, export and restore checks, approved retention and Chris's approval before any legacy writer is removed. | Inspection | AC-R7-01, AC-R7-03 |
| BC-AE30 | The redesign wizard publishes through the ordinary publication protocol with impact preview and recheck, and reads or writes no legacy data. | Integration; E2E | New |
12. Brief items, specialist inputs and unapproved proposals¶
12.1 Brief items this spec owns¶
| Entry | Required treatment | Tracker |
|---|---|---|
| D2-13 | Specify isolated point-in-time recovery (§8.4), rehearse it on an authorised copy with manifests and evidence checks before the first production pilot, and keep production recovery execution under its own authorisation. | T-BC-00 |
The brief also fixes (no owner question): the conversion record shapes and names (§3.3); permitted partial pilot boundaries (BC-R23); wave notice, override and timing rules; the stall limit; the budgets for conversion time and post-conversion performance; and the exact parity tolerances.
12.2 Thresholds (proposed, not approved)¶
- Number of projects converting in parallel in a wave.
- Stall limit for busy Studies during cutover.
- Notice period before a wave, and the recent-activity window for reviewer notices.
- Conversion-time and post-conversion performance budgets, including the largest project.
- Any parity tolerance beyond exact semantic equality.
12.3 Specialist inputs¶
- PRISMA box mapping for converted history (T-SI-05): how pre-conversion coverage gaps appear in flow diagrams.
- Scientific meaning of legacy screening per project: an admin input at conversion (Q-21), not a methodologist approval.
12.4 Ambiguities found while drafting¶
A1. How a converted target-one form behaves. R1 gives target-one forms two handlings
(AutoAccept, RequireHumanReconciliation). Legacy single-reviewer projects have neither: they
export the reviewer's answers and have no accepted results. Options: (a) conversion creates no
accepted results and adds no reconciliation work; the admin can choose AutoAccept later through the
redesign wizard, whose publication impact would then create SingleAnnotator results with system
provenance at that time; (b) conversion sets AutoAccept and creates SingleAnnotator results for
qualifying sessions with "baseline conversion" provenance; © the admin chooses per form in the
wizard. Recommendation: (a), because it is faithful, and legacy Completed sessions are unvalidated
anyway. The mechanism is RS-R04a's conversion-only targetOneHandling = NoAcceptance value in the
reconciliation and screening spec: no automatic result, no
required reconciliation, exports labelled "single annotator, not accepted" (BC-R21). Only conversion
can set it. Later acceptance goes through publication of a new form version that chooses
AutoAccept or RequireHumanReconciliation, whose impact treatment (RS-R11) decides whether
SingleAnnotator results are created, with publication provenance. Both specifications now say the
same thing; the single owner-visible confirm item is RS §12 ("Converted target-one forms").
A2. Who confirms the meaning of legacy screening for projects with no active admin. Options: (a) convert with "Legacy project screening (meaning not confirmed)" and no PRISMA phase until someone confirms; (b) block the project until an admin confirms; © a CAMARADES operator confirms on the owner's behalf. Recommendation: (a). It is faithful (legacy had no PRISMA mapping) and does not leave old projects stuck.
A3. Who approves manifests in universal waves. Options: (a) every project owner approves their own manifest; (b) Chris's wave approval covers every manifest; © Chris's wave approval covers default faithful mappings with no unresolved findings, and project-specific choices need the owner or a delegate. Recommendation: © (BC-R39).
A4. Whether a project admin may defer a scheduled wave. The owner left override rules to the
brief. Recommendation (PROPOSAL): an admin may request one bounded deferral with a reason during
the notice period; it creates a recorded blocker with a review milestone and never makes the project
permanently legacy.
12.5 PROPOSALs an owner may want to see¶
firstCanonicalWriteAt as the exact recovery boundary (BC-R28); legacy Completed counting as
completed by default with the LegacyCompletionUnvalidated label; one form per stage set by default
(BC-R15); allocation as a blocker, never silently disabled (BC-R17); no accepted results at
conversion through NoAcceptance (BC-R21, A1, RS-R04a); deleted projects converting in their deleted
state (BC-R38); wave-level manifest approval scope (BC-R39, A3); deferral rule (A4); conversion never
using Apply anyway (§7).
12.6 Harmonisation notes (5 October 2026)¶
- §3.4, BC-R21, §12.4 A1, §12.5 and §14: converted target-one forms now name RS-R04a's
conversion-only
NoAcceptancevalue, its export label and the publication route toAutoAcceptorRequireHumanReconciliation(RS-R11). BC and RS say the same thing; the single owner-visible confirm item is in RS §12. The §2 related-decisions row cites RS-R04a. - §3.2, §3.3 ("Conversion history events"), §3.4 stage-filter row, BC-R33 and E3: pool baselines now
use SP's envelope field
coverage = BaselineAtTrackingStart, causeBaselineConversion, with earlier pool historyNotRecordedInLegacy(SP §3.5.5, §3.12, §10.4). The earlier text usedCurrentSnapshotOnly, which contradicted §3.2's own example and SP. Session and decision history keepCurrentSnapshotOnly.
13. Amendments to existing package documents¶
- migration-adoption-rollback.md
- Status paragraph: add the universal baseline direction and the hold; R6 is universal conversion, R7 is the retirement milestone.
- §1 principle 2: replace "labelled current snapshots (
historyCoverage)" wording with the legacy-gap state names of §3.2 (keep the meaning). - §1 principle 3: replace "Existing projects adopt one complete scope at a time after a reviewed manifest" with trials, pilots (complete scopes only) and universal waves (whole projects).
- §2 adoption modes: "Reviewed adoption: projects chosen by Chris" becomes opt-in trials and pilots; "Legacy: indefinitely, until adopted or retirement is separately approved" becomes "temporary, until the project's universal wave or the remedy of its recorded blocker".
- §3 domain mapping: replace with §3.4 of this spec, notably the target row (the target is part of the immutable form version, not an operational setting), the reconciled-answers row (Q-35 removed), the single-reviewer row (A1), the allocation row (blocker) and new rows for steps, capacity cap, timeouts, blinding, stage state, overlaps and deleted projects.
- §4 protocol: add the Q-35 premise count to step 1, the wizard review and findings to step 2,
firstCanonicalWriteAtto step 5 and quarantine records to step 6. - §5 table: R6 row becomes "universal baseline conversion waves"; R7 row becomes "legacy-writer retirement milestone"; O2 row notes that outcome conversion is part of each project's baseline.
- §6 restore policy: replace "
PROPOSALuntil Chris answers" with "brief item D2-13 (spec §8.4); rehearsal before the first production pilot; production execution needs separate authorisation". - §1 principle 8 is amended by the access spec §13.
- consistency-model.md
- §6.4: add the routing-rollback window and the
firstCanonicalWriteAtcompare-and-set. - §7.7: name the operation kind
baselineConversion; deferral of busy Studies; stall limit. - §13.1: change "Per D2-13 (recommended;
PROPOSALuntil Chris answers)" to "brief item D2-13"; add the recovery manifest. - §19.3: D2-13 row becomes "brief item; spec-baseline-conversion §8.4".
- versioning-model.md §11: rename
current-onlytoCurrentSnapshotOnlyand "legacy-completed, unvalidated" toLegacyCompletionUnvalidated; tieAuthoredUnder = UnknowntoUnknownAuthoredUnderDefinition; delete the reconciled-answers row (LegacyAuthorityUnknown) and cite Q-35's removal; add the stage-target row. - domain-model.md: §4.9 add the conversion records of §3.3 (inventory,
manifest, quarantine, wave, parity report, recovery manifest) as
PROPOSALs andfirstCanonicalWriteAton the registry; principle 7 keepsLegacyReviewDataAdapterretiring at R7 and adds that originals stay stored. - contracts.md: C16 rollback bullet gains the routing-rollback window and the
universal-wave wording; C9 drops the Q-35 legacy-authority handling; C11 notes conversion
provenance and the discontinuity record in manifests; C20 lists
BaselineConverted,ConversionRolledBack,ConversionQuarantinedand conversion-timeStagePoolBaselineMember. - integrated-plan.md: §5.9 R6 and R7 bullets rewritten per §10.1; §5.10 "Existing real projects stay legacy until R6 adoption" becomes "until a pilot or their universal wave"; §11 decisions list records R4, Q-05, Q-21, D4-16, Q-35 and D2-13 statuses.
- acceptance-criteria.md: §4.31 amend AC-R6-04, 05, 06, 09, 11 and 14 as in §11; replace AC-R6-08 with BC-AE12; AC-R6-15 status becomes confirmed (Q-21 decided); AC-R6-17 becomes "a pilot may convert a complete screening scope when its readers and writers are canonical" (D4-16 decided-amended); add BC-AE06, 07, 14, 15, 19, 21, 22, 24, 25, 26 and 30; §4.32 AC-R7-02 status becomes brief item D2-13 and AC-R7-03 adds the retirement readiness record; remove AC-R4a-12 and C9-T14 (Q-35 removed) in favour of BC-AE11; AC-R2a-29 status becomes brief item D2-13; AC-O2-01r, 02 and 04 and C14-T04 statuses change from pending-Q-05 to confirmed (through R4).
- open-questions-and-assumptions.md: Q-05, Q-21 and D4-16 rows marked decided-amended through R4; Q-35 marked removed with the premise check; D2-13 marked a brief item; D2-16 marked replaced (owned by the RD spec).
- decision-register.md: add the R4 owner direction, R4 amendment, the replaced R4 research finding, Q-35's removal and D2-13's treatment.
- prisma-amendments.md amendment G: per-project adoption becomes per-project conversion inside universal waves.
- g0-dossier.md and the status page: R6 described as universal conversion, R7 as a separate milestone, with no execution authorised.
- owner ledger: add R4's direction and amendment as owner-session entries; mark the OC2 deferral of P9 as superseded by R4's direction for the baseline (outcome-specific mapping details stay with Q-05's plan).
14. Superseded wording¶
| Old wording | New wording | Where it appears today |
|---|---|---|
| "Legacy: Unchanged legacy behaviour ... Indefinitely, until adopted or retirement is separately approved" | Legacy status is temporary until the project's universal wave or the remedy of its recorded blocker | Migration §2 |
| Completed or archived projects "may remain preserved legacy snapshots behind a read-only compatibility reader" | Every project converts to the faithful baseline; no permanent archive adapter (superseded wording 8) | Register "R4 research finding"; condensed R4 package |
| "Reviewed adoption: Existing projects chosen by Chris" and "R6 ... Projects Chris selects" | Opt-in trials and pilots, then universal waves | Migration §2 and §5 |
| "Existing real projects stay legacy until R6 adoption" | Until a pilot or their universal wave | Integrated plan §5.10 |
"Reconciled answers ... LegacyAuthorityUnknown, treated per Q-35" and the mandatory legacy-authority backfill |
Removed; the dry run verifies the no-records premise (superseded wording 7) | Migration §3; versioning model §11; AC-R4a-12; C9-T14; open questions Q-35 |
| "The form's minimum target (an operational setting, D2-05)" | The standard target is part of the immutable form version (superseded wording 3) | Migration §3 stage-targets row |
| "allocation is disabled on adoption unless AL1 is live" | Enabled allocation blocks conversion until AL1 | Migration §3; AC-R6-14 |
| "Single-reviewer studies: No automatic promotion to gold (Q-29); exports label them 'single reviewer, unreconciled'" | Conversion creates no accepted results (A1); converted target-one forms carry NoAcceptance (RS-R04a), labelled "single annotator, not accepted", until the admin publishes AutoAccept or RequireHumanReconciliation |
Migration §3; AC-R6-08 |
| "the 2,023-question project stays on the legacy path even after adoption opens" | The largest project is an acceptance case (superseded wording 12) | D2-16 original recommendation in open questions; AC-R2a-22 premise |
| "Allow admin-initiated adoption for screening-only, unreconciled stages after R3b, reversible until the first canonical write" | Limited pilot scopes only with complete validated reader and writer coverage; the first-canonical-write boundary applies to every conversion | D4-16 row in open questions; AC-R6-17 |
"Restore policy (D2-13, PROPOSAL until Chris answers)" |
Brief item D2-13 with spec §8.4 and a required rehearsal | Migration §6; consistency model §13.1 and §19.3 |
| Staying legacy as a permanent alternative in R4 options | A supported choice during trials and pilots; a temporary blocker during waves | Condensed R4 package options; register "R4 amendment" (refined by "R4 owner direction") |
15. Existing work reused¶
QM v2 PR-C (#2574) is the main earlier work on conversion, with pieces from PR-A (#2572) and
2986's validation rules. **PR-C's migration erases the embedded legacy data from pmStudy, and its¶
rollback is a lossy hand-back to the legacy model** (H-MIG-05, H-MIG-08). Both contradict BC-R27, BC-R29, C16 and AC-M0-04, and neither is carried. Its plan builder, review-state extraction, parity checker and legacy-shaped projection are adapted. The harvest map is authoritative for every verdict and adaptation; nothing is ported while the hold lasts.
| Entries | Verdict | Target section |
|---|---|---|
| H-MIG-01 | Adapt | §3.3 baseline structures; §4.2 dry-run preview (T-BC-01, T-BC-03) |
| H-MIG-04 | Adapt | §3.2 to §3.4 converted evidence and outcome rows (T-BC-03, T-BC-05) |
| H-DOM-22 | Reference only | §3.4 outcome rows (T-BC-05) |
| H-MIG-06, H-MIG-07 | Adapt | §3.3 parity report; §4.4 shadow copy and parity (T-BC-06) |
| H-DOM-06, H-DOM-07, H-DOM-14, H-VAL-02 | Adapt | §3.3 inventory; §4.2; §8 unmappable values (T-BC-01) |
| H-DOM-19 | Adapt | §4.5 cutover and the R0 floor (C16; T-BC-06) |
| H-API-06 | Reference only | §4.5; the R0 writer inventory (T-BC-01) |
| H-MIG-02, H-MIG-03, H-MIG-05, H-MIG-08, H-MIG-09, H-DOM-12, H-DOM-20 | Avoid | BC-R01, BC-R25 to BC-R29; §4.9, §4.10 |
What this specification requires that the earlier work lacks.
- Originals untouched. Conversion never modifies or deletes legacy originals (BC-R29); PR-C clears the embedded data and saves the Study by full replace.
- Routing rollback only. Before the first canonical write, recorded exactly, rollback restores routing to intact legacy data; after it, recovery moves forward (BC-R27, BC-R28). PR-C rebuilds legacy records from the extracted ones and flattens later work into them.
- Faithful, not repaired. No invented parents or versions (BC-R04, BC-R09), and legacy data is never validated against new authoring rules; failures become findings and quarantine (BC-R26). PR-C repairs orphans and throws on rules that #2648 and #2651 have since relaxed.
- Legacy-gap states for missing time, author, wording and completion checks (§3.2, BC-R08), and the original time and author carried (BC-R08, BC-R09), with conversion provenance alongside (BC-R10); PR-C stamps the migration time and actor.
- Deterministic, idempotent and resumable runs with persisted inventories, manifests, attempts, parity reports and quarantine records (§3.3, BC-R25); PR-C is not transactional, not idempotent and has no caller.
- Global system questions pinned by version (H-DOM-07); PR-C's per-project copies let only one project ever migrate.
- A real dry run under a read-only role, with counts and the Q-35 premise check (§4.2); PR-C's dry run reads no Study.
- Every current embedded field, including
main's six newer session fields, and the original question wording.