Source and status inventory¶
Temporary planning evidence; planning only. This page records what exists on main, what
exists only in open PRs, what is documented but not built, and which existing documents conflict
with the latest owner decisions.
How it was gathered:
- Baseline:
main=origin/main= remotemain=78c6d097d(3 October 2026, 01:35 UTC), confirmed withgit rev-parseandgit ls-remote. - Re-checked at
2949ca3a7(03:39 UTC) andc59d9d0f1(04:47 UTC, the remotemainat the last check). The changes since the baseline are FEAT-024 fold slice 6 (#3948, #3949), the FEAT-024 question-answer staleness fix (#3955), an identity registration fix (#3954), auth-migration S30 documents (#3930) and the generated API client. Among them, a refactor of the reservation claim-stage writes keeps claims keyed by stage and investigator. No other code area this plan relies on changed. - Read-only sub-agents (Opus) inspected code and documents; their reports are summarised here with file and line references.
- Load-bearing security and data claims were re-checked directly (marked re-verified). After the adversarial reviews, their new code claims were spot-checked directly too (marked re-verified after review).
-
PR states were read live with
ghat about 04:52 BST (03:52 UTC), rechecked at 05:48 BST, and refreshed for the programmes in programme integration at 15:18 BST (mainde3e98c59; cluster-gitopsorigin/mainea972fd6). -
Owner-session re-check (5 October 2026, 00:33 UTC). For the owner-session integration the following were re-read directly, read-only: remote
main(git ls-remote:5245941e9); the worktree'ssrc/(identical tomain:git diff --stat 5245941e9 HEAD -- srcis empty at worktree HEAD1a450cbaa); the web app's PWA files (§1 item 27); the account-deletion path (§1 item 28);docs/decisions/and the uncommitted deletion-lifecycle worktree (§1 item 17); and the live state of the PRs and issues named in §3 and §4 (gh pr view,gh issue view). Rows that this re-check changed say so; everything else keeps its earlier reading.
Limits: no runtime checks, no database reads, and no reading of runtime flag overrides; flag
values in environments come from cluster-gitops values.yaml and may differ live. "UNVERIFIED"
marks anything that couldn't be confirmed.
Owner session of 4–5 October 2026. The consolidation and the nine specifications supersede older conflicting decisions. This page records facts, so most of it stands. Where a row cites a decision the owner session changed (DP6/DP7 cross-stage routing, BL1 stage ownership, D2-12's alias merge, D2-14's anonymisation, ADR-014's physical deletion), the row is annotated and the earlier text kept. Feature implementation is on hold (owner, 5 October 2026); nothing here authorises code, migrations or production activation.
Changes since the earlier research baseline (5861b5844, 2 October): FEAT-024 fold slices 4,
5 and 6 (#3925, #3926, #3948, #3949), batch risk of bias (#3931), auth-migration documents (#3930)
and two E2E fixes. No change to questions, sessions, screening, reconciliation, outcomes,
exports or permissions.
1. The facts that most constrain the plan¶
- No versioning exists for questions, forms, sessions or answers. Questions are edited in
place inside the Project document, and system questions are rebuilt from code on every read
(
Project.cs:109-110, 223-247). The QM v2 domain exists only on dormant PRs (#2461, #2572–#2575); searchingsrcfor AQVersion, StageQuestionSet or SessionVersion finds nothing. - Deleting a question hard-deletes every answer to it and its descendants across the
project. The atomicity gap is acknowledged in the code (issue #3088) —
ProjectManagementService.cs:201-222, re-verified. - Answers already belong to reviewer + question across stages, but sessions are per stage.
A save removes all of the caller's answers to any question in the stage's form, whatever stage
they were saved in, then adds the submitted ones (
ExtractionInfo.cs:183-194). There is one session per (study, stage, reviewer, reconciliation flag), and only one reconciliation session per stage whoever the reconciler is (ExtractionInfo.cs:202-208). A session is a filtered view (AnnotationSession.cs:149-164). Saving a shared question in stage B silently changes what stage A's session shows (the "little DOMS" investigation). - No drafts, autosave or immutable history on the server. Complete is a status flag;
reopening is a save with Incomplete. AF2 keeps drafts in memory only
(
annotation-form-v2.store.ts:176-179), and the web rules forbid adding per-answer server saves implicitly (src/services/web/CLAUDE.md:343-344). Reviewers can hard-delete their own session and all its answers and outcome rows (ReviewController.cs:86→ExtractionInfo.DeleteSession). - The server never enforces required answers.
Optionalis only ever assigned (AnnotationQuestion.cs:55, 227); validation is structural only (AnnotationRelationshipValidator.cs:23-275) — re-verified. Legacy "Completed" sessions were therefore never validated on the server. - Screening is one Include/Exclude decision per reviewer per project, judged against one
project-wide threshold, with
StageIdoverwritten on re-screen (ScreeningInfo.cs:79-142,Screening.cs:33-38). ScreeningProfile,screeningOutcomes[], StudyLifecycleStatus, exclusion reasons and screening questions don't exist in code, although the rootCLAUDE.mddescribes them in the present tense. - Reconciliation exists in a legacy form.
- A study is ready when completed sessions ≥
SessionCountTarget. - There is one shared reconciliation session per study and stage, editable by anyone with the Reconcile grant.
- Reconciled answers are one overwritten set per question, shared across stages.
- Counters are two booleans.
- The reconcile endpoint maps every session on the study into the response
(
ReviewController.cs:1586-1628,StudyDto.cs:53-58, re-verified). The agent reports the session DTO includesInvestigatorId(StatsWithIncompleteDto.cs:14-31; not independently re-checked). - Reconciliation reserves nothing (
StageReviewService.cs:153, re-verified after review). - There are no gold-snapshot, adjudication or query entities.
- Owner session (Q-35 removed, 4 October 2026): the owner says reconciliation "has not been
fully implemented" and no existing reconciliation records are assumed. The legacy code above can
still write a shared reconciliation session per study and stage, so whether production holds any
is an open fact: the read-only production count on 3 October timed out on an unindexed scan and
was not retried (programme integration §1).
Every conversion dry run counts legacy reconciled records; any found stop that project's case for
a decision by Chris (BC-R20). No
LegacyAuthorityUnknownbackfill is designed. - The reconciliation UI is read-only.
reconcile/:studyIdrenders every candidate session as read-only cards, two per row (a third wraps). The reconciler has no form on that route, and no navigation links to it (stage-reconcile.component.html:18-46,stage.routes.ts:41-61). AF2's reconcile host is read-only by rule, stage-review and preview hard-fail on reconciliation, and the extraction and Experiment carve-outs on non-review hosts lift only in AF2 Phase 4 PR 9 (src/services/web/CLAUDE.mdAF2 section, re-verified after review). - Outcome direction is a per-reviewer answer copied onto rows. Direction, units, average
type and error type are system questions under Outcome Assessment, and the client copies them
into every outcome row; the export reads some from the row and some from the annotation
(
AnnotationQuestion.cs:537-661,annotation-form-submission.ts:106-109,OutcomeDataFormatRowWriter.cs:205-211).GreaterIsWorseis a non-nullablebool(OutcomeData.cs:39), and the client defaults are directionfalse, error typeSD, average typemeanand zero animals (annotation-form-outcome-topology.ts:40-43, re-verified after review), so stored values can't distinguish an answer from an untouched default. There is no outcome-measure entity and no event-count shape (TimePoint= Time/Average/Error). - Stages are three flat modes plus the D7 closed configuration (ScreeningOnly,
AnnotationOnly, Combined with Allow/Stop). They have an Active switch only: no steps, no
completion state, no rename or delete (
Stage.cs,StageReviewConfiguration.cs). The D7 grouped configuration has a reader and writer floor (#3732) but no migration tool (#3742 is a draft with no files). - The review-eligibility programme is the existing admission authority. It has 14 actions,
typed screening/annotation claims, a claim-revocation outbox and guarded settings PUT, all
behind the default-off
reviewEligibilityPolicyflag. Enabling it requires migrating legacy reservations first (Study.cs:346, re-verified after review). The browser doesn't yet read its eligibility response, and still applies #3551's universal screening-complete veto (S5 audit, #3741). Its flag reaches the API host only (env-mapping.yaml, theservices: [api]block). Per session memory, Chris paused the programme on 25 September until the statistics work finishes; the repository does not record the pause (#3746 had activity on 1 October); recheck before F3. -
Eligibility decisions and later owner decisions.
- Eligibility D3a ("no closure/reopening state machine") is superseded for the new stage model by LC1/RX2 (3 October) under the precedence rule.
- Eligibility D3b ("annotation has no screening prerequisite", pinned by
ReviewEligibilityPolicyTests.cs:176) becomes the behaviour of independent steps, with configured dependencies following DP6/DP7. Owner session (Q-15 replaced, 4 October 2026): configured dependencies exist only between steps inside a stage. The DP7 cross-stage part is superseded: each stage's study filter defines its pool, and there is no incoming dependency gate into a stage (SP spec §3.3, §3.4). - Eligibility D5 concerns excluded work (preserve new-annotation exclusion, keep saved-work resumption, no new direct-access ban). It is consistent with EW1 and the veto and carries over unchanged. Owner session: Q-28 and the continuation amendment (OS-A05) keep saved-work completion after exclusion by default and add continuation after any filter-driven pool departure; hidden excluded saved work stays a display sub-setting (D3-09 brief item).
See §6 and Q-24. 13. Groups are fixed. Only the built-in Administrator group is reachable. Custom groups exist in the domain model (
ProjectSecuritySettings.cs:25-42), but no code creates them. The authorization programme gates custom groups on membership schema 1 applied in production (its gate G-D, which this plan calls X-AUTH-SCHEMA; it needs a migration runner WP-M1 that doesn't exist yet, then WP-M2) and plans their administration, including the generalised permissions dialog, as WP11 after WP9 explanations; #2224 is reference material for WP11 (its decision D10). Production is entirely schema 0. Per-member stage grants have no API writer. 14. The ownership-transfer rule is not enforced.ResourceSecurity.jsonmakesChangeOwnerowner-only, but no endpoint usesProjectChangeOwnerPolicy.PATCH /api/projects/{id}requires onlyProjectEditPolicy(Administrator group) andProject.UpdatecallsChangeProjectOwnershipwhenOwnerIddiffers (ProjectController.cs:365-390,Project.cs:855-883,ProjectUpdateDto.cs:17) — re-verified. The permission-update endpoints also accept owner-reserved activities (ProjectController.cs:1303-1320, per review C). This contradicts PM1's owner-only transfer (§7). 15. Materialized statistics are dark and narrower than they look. - Production has nothing; staging runs the ProjectScreening family for one pilot project and pins the fold flag on for both hosts (cluster-gitopssyrf/environments/staging/{api,project-management}/values.yaml, commitc4412000of 2 October, read atea972fd6; the comment says "staging pilot only (Chris, 2026-10-01)" and a project still needs an explicit admin enable; whether the project is in fold mode is unverified). - Fold protocol v4; slices 0–7 merged (slice 7 docs #3962). Gate (b) was a provisional fail on a loaded host; update: it failed on latency in the idle-host rerun (Bramble, 3 October 2026, 22:38–23:01 UTC; zero statistics-caused conflicts; #3510); the soak (#3510, #3952) has not started. Enabling fold mode on the production database is refused in code (commit89d295734). Re-check, 5 October 2026 00:33 UTC (gh issue view 3510): no later gate (b) result is posted. A 4 October comment records that Chris revised the soak gate: about 24 hours of isolated soak on Bramble (#3952) plus one week of passive checking on staging with every family on for the pilot, replacing the 7-day rule. The soak driver PR #4010 was closed without merging at 00:33 UTC on 5 October (reason not read); #4012 (read-only projection-read admin route) is open. Production readiness stays provisional (D3-10 brief item; RI-R56). - Question-answer statistics are keyed by question only. The reservedStageQuestionVersionscope is stage-keyed and never written, so PS1's stage-free usage needs new scope kinds. - "Enough = 2" is hard-coded at three sites:StudyStats.cs:353-355, FEAT-024'sAnnotationThresholds.MinimumNumberSessions(an input of the shared configuration digest) and the study-library session filter (StudyRepository.cs:1665, 1712, 1725, #3979). - FEAT-024 explicitly excludes broad agreement statistics and outcome-level statistics. 16. Several counters and claim authorities already coexist: session tallies, slot reservations (one per reviewer per stage, typed claims), reviewer presence, allocation regimes, statistics rows with pending entries, FEAT-024 source-operation receipts, the project answer tally, and bulk-update study locks (ADR-020,Study.cs:242). New work must extend these rather than add another. 17. Exports are current-state only, and deletion is disabled. As-of modes are reserved only in open #2461/#2574 and accepted only for CurrentState. Screening decisions and answers are overwritten in place, so as-of review state can't be rebuilt from current data. Search, import-job and project deletion routes fail closed with a 503 (DeletionLifecycleUnavailableException,SearchController.cs:122, 134,ProjectController.cs:410) until a reversible-deletion scheduler exists; thedeletionLifecycleflag only chooses a message. Only service and repository paths still hard-delete, andStudyRepository.cs:1129-1130says "Search deletion is disabled today" (re-verified after review). An earlier version of this page wrongly said that removing a search hard-deletes its studies. - Owner session (D3-12 decided-amended through O1, 4 October 2026): ordinary whole-project deletion is reversible. It hides the project, blocks review and editing, stops allocations and notices, releases places and keeps drafts, evidence and history for restoration from a restricted "Deleted projects" view. Permanent physical erasure is a separate policy that is not approved (T-POL-01). The uncommitted deletion design's 24-hour physical deletion therefore no longer applies to projects (ACD spec §3.3). - ADR number clash (re-checked 5 October 2026). The uncommitted deletion design is the untracked filedocs/decisions/ADR-014-reversible-deletion-and-permanent-tombstones.mdin.worktrees/bulk-pdf-deletion-lifecycle(git status:??). Onmain, ADR-014 is alreadydocs/decisions/ADR-014-integrated-study-pdf-viewer.md(commitb4c421b76). The deletion ADR needs a new number when it is committed. ADR-021 was free at this check, but #3961 took it for #3986's messaging ADR when it merged on 5 October 2026 (01:54 BST), so ADR-022 is the next free number. References to "ADR-014" for deletion in this package mean that uncommitted document. 18. No PRISMA, deduplication, Citation, Publication or lifecycle code exists.SystematicSearchlacks the phase-7sourceTypeMUST. The FEAT-011 package is Approved and is the binding specification. 19. Two question editors coexist, and all default entry points lead to the legacy one. The new tabbed editor (Design/Assign/Preview) atadmin/questionsis guarded only by the design permission;newQuestionManagementjust hides its nav link. It saves through the old schema-v0 API, locks answered questions instead of versioning them, has only seven hard-coded categories, and its 17 specs are excluded from CI (#3655). 20. AF2 is merged but off almost everywhere.annotationFormV2is on in staging only;stageReviewRedesignandstageReviewDockvieware off in every environment; production has only ever used AF1. AF2 has no autosave and no "Complete anyway". AF2 eligibility admits only annotation and combined stages, so screening-only steps aren't rendered by AF2. 21. Study's embedded value objects use strict class maps.ScreeningInfo,ExtractionInfoandSessionTallyare mapped withAutoMap()and no extra-element tolerance (StudyRepository.cs:3176-3231). By contrast,Entitysubclasses carry[BsonExtraElements](Entity.cs:21) and FEAT-024's pending-statistics maps callSetIgnoreExtraElements(true)(StudyPendingStatisticsClassMaps.cs) (re-verified after review). An older binary reading a document with new fields in those three types throws rather than ignoring them, which is why R0 exists. 22. System-question structure depends onProject.SystemQuestionVersion. In v0 and v1 projects the outcome error-type question has a different parent and option filters (AnnotationQuestion.cs:559-592, re-verified after review), so a published form can't pin live system questions. 23. Support impersonation has an edit mode that admits side-effecting review actions under a valid edit context (ImpersonationSideEffectAttribute, re-verified after review). Review data records the effective investigator; the canonical model adds a real-actor field (per review B; not traced end to end). 24. Saved Dockview layouts are per reviewer per capability slot (screening, annotation, combined). The API validates allowed panel keys and one instance of each capability panel (docs/architecture/dockview-layout-migration.md, re-verified after review), so new panels and step kinds need a layout-contract change. 25. Exports can unmask identities regardless of blinding. The export page lets any ExportData holder choose unblinded output ("UNMASK DATA"), independent of stage blinding and candidate isolation (per review C). -
Claims exist only when tracking is on, and tracking is off everywhere deployed. Claims, capacity guards and typed admission run only when
ActiveReviewerTrackingEnabled && SignalRActive; the flag is unset in production, staging and preview and true in the E2E stack (appsettings.e2etest.json). Reconciliation is excluded at every tracking layer. Enabling tracking is a FEAT-024 durable reviewer-mode transition whose code (AdvanceModeEpochAsync, M15) has no caller. Presence snapshots carry claim holders' identities to every member who can view studies. Owner session: the production capacity route (D3-16) is a brief item: tracking is enabled per admitted pilot project, never fleet-wide; for canonical projects the scope is proposed to be the project's admission record (SP-AMB-12,PROPOSAL). Capacity, the inactivity timeout and the in-progress limit are form-owned (D2-07, D3-17, D3-18). Presence names need the Monitor capability and never cross reconciliation blinding (D3-20 brief item). #3876 was re-checked open on 5 October 2026. -
The web app is very likely not installable as a PWA today (re-checked 5 October 2026).
src/services/web/src/site.webmanifestexists with emptynameandshort_name,display: standalone, white theme and background colours and icons at/android-chrome-192x192.pngand/android-chrome-512x512.png. The icon files live atsrc/assets/img/android-chrome-192x192.pngand-512x512.png, so the manifest's root paths do not match the built location.angular.jsonlists onlysrc/favicon.ico,src/assetsand library globs as assets, so the manifest is probably not copied into the build.src/index.htmlhastheme-color,viewportand threeapple-mobile-web-app-*tags and no<link rel="manifest">. There is no@angular/service-workerdependency, nongsw-config.jsonand no service-worker reference in the web source. Nothing was built or run, so installability stays UNVERIFIED. Existing metadata is not evidence of PWA readiness. PWA work is an exploration beyond the MVP (OS-A22; UX spec §3.11); no offline writes are authorised. - Account deletion deactivates; it does not anonymise (re-checked 5 October 2026).
On the unguarded path,
AccountController.DeleteProfiledeletes the Identity account and then callsInvestigator.DeactivateAccount(), which only setsDeactivated = true(AccountController.cs:266-337;Investigator.cs:215-218). When application authority is enforced, the controller hands over to the M1c guarded deletion service (DeleteProfileGuardedAsync,AccountController.cs:369), which was not traced here. No code path found anonymises thepmInvestigatorrecord (a case-insensitive search ofsrcfor "anonymis" finds only display shaping for statistics and realtime pushes, and cookie-consent text): it keeps the person's name, and submitted work keeps its attribution. The endpoint accepts aremovePersonalDataquery parameter that nothing in the controller reads (only the signature, the generated client and tests mention it). The owner session keeps this as the ordinary behaviour: named attribution is retained and an identity-erasure process is not decided (D2-14 decided-amended;T-POL-02; ACD spec §3.1). The package's earlier "anonymised identity" wording is superseded.
2. Implementation inventory by area (main, 78c6d097d)¶
Re-checked at 2949ca3a7 and c59d9d0f1; only the statistics row changed.
| Area | Verified on main |
Gaps against the plan | Conflicts with decisions |
|---|---|---|---|
| Questions and editors | Embedded Project._annotationQuestions; fields AnnotationQuestion.cs:107-150; conditional parents and filtered options (Target.cs, OptionInfo.cs); lookups; placement rules for new questions; in-place edit; cascade delete; same-project copy; system questions vary by SystemQuestionVersion. New editor: Design/Assign/Preview with locks, same-parent drag only, debug text left in the template. Legacy editor: create/delete only, Bootstrap. |
Versions, publication, library, import (in #3934 only), profile-owned questions, custom categories, re-parenting, response modes, system-question snapshots | FV1–FV3 (no versions); DP4 (unknown categories refused) |
| Sessions and answers | Per-stage sessions; stage-independent answer replacement; structural validation; SessionWriteOwnership (#3671); client-supplied IDs; hard session delete. StudyPdfCorrection (pmStudyPdfCorrection; mongodb-reference.md:103 still says pmStudyCorrection), the three BulkPdfUpload* roots inside ProjectAggregate/, the ADR-020 and M5b operation stores and the FEAT-024 fold are Study writers for R0's inventory |
Form identity, shared sessions, drafts, immutable versions, required-answer validation, provenance, withdrawal instead of delete | SF1–SF3, SL1–SL3, PV1 |
| Stages | ReviewMode; D7 configuration types; SessionCountTarget falling back to the project threshold; AllowSelfReconciliation with no writer; workload shares on annotation-only, disabled stages; guarded review-settings endpoints (flagged); 3-step create dialog; settings page with mock study filters and mock stage permissions |
Steps, dependencies, routing, lifecycle, versioned settings. Owner session: stage study filter versions (AND/OR clauses on profile outcomes and reconciled answers), steps with in-stage dependencies and exclusion-stop, continuation settings, form-owned capacity, timeout and limits, pool history events | DP6/DP7, PV2, RX2/LC1, SF2 (stage target; #3732 adds a per-stage override). Owner session: DP7's cross-stage routing is superseded by the stage study filter (Q-15 replaced); the standard target is part of the immutable form version (OS-A12) |
| Screening | Project-level method/criteria/keywords; Include/Exclude only; ReviewEligibilityPolicy (14 actions); sufficiency guard for new votes | Profiles, eligibility questions, reasons, profile outcomes, derived decisions | DP2–DP5, RX1 |
| Reconciliation | Legacy readiness, session, overwrite model; reconcile grant (#3565); no editor exclusion: reconciliation consumes no reservations and uses no claim or presence at any layer (StageReviewService.cs:67-70, :153, stage-review-presence-policy.ts:17, per RT-01), and "Next" picks an unclaimed study at random; AF2 reconcile host renders N read-only candidate cards for non-extraction pools |
Editable reconciliation form and host, task identity, gold snapshots, matching, assignment, queries, blinding policy. Owner session: AcceptedResultVersion authorities, one-candidate human reconciliation (OS-A28), screening adjudication tasks with member or group assignment (OS-A13), hints with click-to-fill (OS-A04) |
RE1–RE5, RA1–RA5, GS1, BL1, SF4. Owner session: BL1 moves to the form (annotation) and profile (screening), blinded by default, with context-local aliases (OS-A02, OS-A03) |
| Outcomes | OutcomeData per (stage, outcome, cohort, experiment, investigator, reconciled); GreaterIsWorse a non-nullable bool; TimePoint (Time/Average/Error); duplicated NumberOfAnimals; AF2 matrix, cell editor, spreadsheet, graph assignment |
Measures, schemas, event counts, custom fields, versioned direction | OC1, ODIR1 |
| Permissions | 25 project + 4 stage activities; owner-only ChangeOwner/AssignPermissions/Delete in the catalogue; ChangeOwner unenforced; permission updates accept owner-reserved activities; ProjectAuthorityEvaluator (dark, enforced mode only); working group×activity PermissionsDialogComponent used only for chart visibility; Membership UI is Administrator/Reviewer only; route guard typo project.editMembership (project-admin.routes.ts:36; review C judges it most likely a no-op; UNVERIFIED) |
Configurable groups, scoped grants UI, delegation envelope, new capabilities | PM1, PM2 |
| Statistics (FEAT-024) | 10 families; fold protocol v4; slices 0–7, #3955 and #3956 merged; gate (b) failed on latency on an idle host (3 October, #3510; no later result at the 5 October re-check, when the soak gate had been revised on 4 October, §1 item 15); production fold enable refused in code; staging fold flag pinned on for both hosts (cluster-gitops c4412000; "staging pilot only"); positive-proof-only stage evidence (StageReviewStatisticsEvidence.cs:40-124); "enough = 2" inside the configuration digest |
New families over canonical sources (usage, question-version answers, profile grain); target-aware classification; scoped-rebuild service API | PS1–PS3, SF2 |
| Allocation, presence, claims | Allocation MVP and regime provenance (#3603) merged, dark; reviewEligibilityPolicy and proportionalStudyAllocation reach the API host only (AP-08); reviewer validation blocked on #3251; typed slot reservations keyed by stage and investigator, created only when tracking is on (activeReviewerTrackingEnabled ∧ signalRActive; with it off no claim is created, saves are unguarded and EnforceAnnotationTarget does nothing, RT-02); ReviewerPresence and ReviewSessionConnection roots, both keyed by stage (presence snapshots name reservation holders, identities included, to every member who can view studies, #3892); tracking off in every deployed environment, on in E2E, and enabling it is a FEAT-024 durable reviewer-mode transition whose code (AdvanceModeEpochAsync, M15) has no caller; reconciliation excluded; maxInProgressSessions effectively on through appsettings (API true, PM false) |
Per-reviewer membership projection; claim contract v2; reconciliation task editor claim; production claims route; shared-form allocation | SF1/SF2 (stage-keyed); RA1 (no editor exclusion) |
| Batches | None on main; #3939 open and conflicting (lazy shared frontier, legacy-keyed completion, PM-only flag block); #3936 plan open |
Evidence seam; pool-entry-based membership; durable opening | FEAT-026 README rejects "arbitrary sequential stage-step model" (DP6) and "a stage closure concept" (LC1/RX2) |
| Export and history | Current-state CSV (long, wide, screening, outcome, bibliographic), streamed to the browser; blinding level option open to any ExportData holder; OnlyCompleted forwarded but unused by writers; export authorization (#3243) |
Previous versions, as-of, manifests, gold export, export disclosure contract | EX1/EX2 |
| PRISMA, dedup, import, deletion | RIS import done (FEAT-022); reference-file screening columns call AddScreening; bulk update v2 with study locks (flagged); search/project deletion routes fail closed pending the reversible-deletion scheduler |
Citation, Publication, source type, retrieval status, pool entry, dedup, report; reversible deletion. FEAT-012 names pmDedupBatch (staging, 7-day TTL) and offers pmDedupAuditLog as the separate-collection option; the plan uses pmDedupAuditLedger. Owner session: consolidated Study merge with reversible unmerge (OS-A29); external and AI-model screening imports (OS-A20); reversible project deletion and restoration (OS-A25) |
PR1-compatible (nothing exists yet). Owner session: the uncommitted deletion design's physical deletion conflicts with D3-12 as amended (§1 item 17) |
| Setup | CreateProjectWizard (basic details → screening criteria → project setup; Living Search/ML disabled); 8-task ProjectSetup checklist (first stage only, legacy links) kept in nav by a 21 September decision | Guided replacement, templates, profile templates | SET2 (replace the content, keep the nav placement) |
| Reviewer UI | Legacy grid default; redesigned shell flagged; standard workspace and Dockview (flagged, "evaluation only"); equal-weight decision card; AF2 tabs, entity cards, Focus, branch tabs, numbering, action bar, outcome matrix; presence banners only; review preferences and layouts saved server-side | Drafts/history UI, needs-updating, Fix, steps strip, screening renderer, compact population context, "Complete anyway". Owner session: full annotation on phones and tablets at launch (D3-05), Draft auto-saved / Version checkpoint saved / Complete status (OS-A21), My work and badge (D3-07), reviewer-pool browsing and Saved work (OS-A27, OS-A05) | SL1–SL3, SF5, RE2 (reconciliation only) |
| PWA and installability (owner session) | Manifest present but not linked from index.html and probably not built; icon paths do not match; no service worker (§1 item 27) |
Feasibility exploration beyond the MVP only (OS-A22) | None; existing metadata is not evidence of readiness |
| Account deletion (owner session) | Identity account deleted, then Investigator.Deactivated = true; no anonymisation; removePersonalData unread (§1 item 28) |
Display of "(account deleted)" and joining-terms text (PROPOSAL, ACD spec §3.1) |
None with D2-14 as amended (named attribution retained); identity erasure not decided (T-POL-02) |
Design system: Angular/Material/CDK ^22.1.0, NgRx 21.1.1, Dockview 8.2,
Handsontable 18. The theme is a hybrid of M2 components and M3 tokens; dark mode needs
themeToggle (off). Zoneless switch shipped but is off everywhere; new code must avoid new
NgZone call sites.
3. Programme and feature documents¶
Doc status is the front-matter status. "Impl" uses Verified / Partial / Planned. Unless stated,
PRs are authored by chrissena (Chris's account, used by his delivery sessions); delivery
owners per lane are named at G0.
| Feature / programme | IDs | Doc status | Impl | Owning PRs (author) | Main conflicts |
|---|---|---|---|---|---|
| Question Management | FEAT-003 | In-Review (Feb) | Partial (UI on legacy API) | #2387 open | FV1–FV3, SF1/SF2 |
| QM v2 implementation | Epic #2488 | qm-v2-context Approved (Apr) | Planned (dormant PRs) | #2461 draft; #2572–#2575 | SF1/SF2, FV2, ODIR1 (per-row direction) |
| Annotation versioning | FEAT-001 | In-Review / design session Approved (Feb) | Planned | — | Per-stage question sets; previous-version-only checks; pendingAnswer drafts; auto-promotion |
| Annotation Form v2 and stage-review redesign | FEAT-002 | In-Review (Sep); STATUS stale | Verified, default off | ~40 merged; #3546, #3543, #3017, #3288 open | SF1 (EntityOrder on per-stage session) |
| Question extensibility | ADR-011; ADR-017 (only in #2812) | Approved (Sep) | Partial (answer labels only) | #2812, #2802 open | FV1 (interim definitionVersion policy) |
| Template/bulk import | delivery map 2b–2g | Planning merged (#2779) | Planned | #3934, #2781 (both conflicting) | DP4 gap, FV1 |
| Library/cross-project sharing | QM-10, SHARE-*, D27/D36 | Draft | Planned | — | DP4 (copy, not reference) |
| Answer validation | FEAT-017/020/027 | Draft/Approved | Partial | #2986, #2987, #2629 open | #2987 "AnnotationProfile" name collision |
| Category guidance | AF2 rev. 2 §6.5 | — | Verified | #3398, #3406, #3453 | SF1 (per-stage override) |
| Reviewer layouts / Dockview | contract + migration doc | Approved / In-Review | Verified, default off | #3225, #3230, #3384… | Panel model changes need a contract amendment |
| Stage-review design parity | handover 2026-09-21 | — | Partial | #3546 | SET2 (nav placement only) |
| Outcomes, experiments, cohorts | — | No schema doc | Verified (old model) | AF2 phase 4 | ODIR1, OC1 |
| Classification and entity types | — | No main doc | Planned | — | TC1 (categories are the legacy types) |
| Project templates | FEAT-014 | Draft (2025-12) | Planned | — | TC1, SET2 |
| Setup wizard and checklist | FEAT-023 nav | In-Review | Verified | M3 nav PRs | SET2 |
| M3 navigation (rail, checklist footer) | navigation plan | — | Verified (September) | merged | IA changes coordinate with it |
| Screening profiles, annotations, stage settings, stage filtering | FEAT-007/009/010/008 | In-Review (Feb) | Planned | #2621 draft | DP4, DP6, DP7. Owner session: FEAT-008's Filter Set becomes the stage study filter version (Q-15 replaced; SP spec §13); FEAT-007 profiles gain Unsure, tie policy, discussion, rationale, blinding and source policy in the immutable profile version |
| Review eligibility programme | S1–S6, D1–D8 | In-Review (Sep) | Partial, flagged (API host only); paused 25 Sep (memory, not in the repository) | Merged #3579, #3646, #3659, #3663, #3691, #3695, #3719, #3732, #3736; open #3746 (conflicting), #3742 (no files), #3741; S4-C and S6b have no PR. Re-checked 5 October 2026: #3746 conflicting, #3742 draft, #3741 draft and now conflicting | DP6 (D3b), RX2/LC1 (D3a); D8 unmapped (D3-09). Owner session: D3-09 is a brief item (T-SP-00); D8 maps onto the step, filter and continuation model (SP spec §12.1) |
| Reconciliation | FEAT-006, D1–D50 | In-Review / Draft (Feb) | Legacy only | #3565 | RE4, SF4/RE3, BL1, RE2, GS1 (auto-promotion, $unset). Owner session: single-annotator acceptance is a configurable AutoAccept versus required human reconciliation (Q-29, R1 final); blinding is form- or profile-owned |
| PRISMA 2020 | FEAT-011 | Approved (Feb/Mar) | Planned | #2398 docs | PR1-compatible; amendments A–J needed (A–P after the owner session). Owner session: StudyEnteredPool is renamed WorkFirstReleased; reporting prioritises actual review through a stage (OS-A09; T-SI-05) |
| Deduplication | FEAT-012 | Approved spec | Planned | — | Tracker uses superseded ImportRecord. Owner session: D2-12's alias merge is replaced by one consolidated current Study with reversible unmerge (OS-A29; DM spec) |
| Reversible deletion lifecycle | ADR-014 (uncommitted worktree .worktrees/bulk-pdf-deletion-lifecycle); deletionLifecycle flag. Re-checked 5 October 2026: the number 014 is taken on main by the integrated PDF viewer ADR, so this ADR needs a new number (§1 item 17) |
ADR-014 records 12 August product decisions (24-hour grace, then physical deletion with tombstones) | Not built; routes fail closed | — (owner to confirm) | Amendment J and QD1 (identification history); D3-12. Owner session: D3-12 decided-amended (O1): ordinary project deletion is reversible; permanent erasure is unapproved (T-POL-01) |
| PDF acquisition and processing | Bulk PDF upload, PDF Agent, Study Management Processing, PDF corrections | Various | Partial, feature-off | #3947 (PDF proposals) and merged work | P1 retrieval status |
| RIS import | FEAT-022 | Completed | Verified | #2971, #3004 | — |
| Materialized statistics | FEAT-024; ADR-018/019 | Approved/In-Review (STATUS stale: slice 7 and fold flag) | Partial (slices 0–7 merged, dark; gate (b) failed on latency on an idle host, 3 October, #3510) | No FEAT-024 PR open; #3840, #3960, #3845, #3506, #3524, #3510, #3952 open. Re-checked 5 October 2026: #3510, #3952 and #3524 open; soak gate revised 4 October; #4010 closed unmerged; #4012 open | PS1–PS3 gap; fixed two in the digest. Owner session: D3-10 and D3-11 are brief items (RI-R51 to RI-R56) |
| Question-answer statistics | FEAT-024 family | In-Review | Partial (bug #3840) | #3562 | No version dimension |
| Proportional allocation | FEAT-025 | In-Review (STATUS stale: #3603 shown pending) | Partial (dark; no human acceptance) | #3327 (conflicting); #3251, #3252, #3264, #3269, #3321, #3745 open | Annotation-only, stage-keyed |
| Active reviewer tracking | ADR-008 (number duplicated) | Draft; feature narrative stale (ActiveReviewSession) |
Verified, off in every deployed environment, on in E2E | #2467, #3008, #3014, #3719; #3876 deferred; #2446 open | RA1 (reconciliation excluded); SF1/SF2 (stage-keyed) |
| Progressive batches | FEAT-026 (PR only) | In-Review (PR) | Planned (implementation PR conflicting) | #3936, #3939 (both re-checked unchanged on 5 October 2026: #3936 mergeable, #3939 conflicting) | DP6, RX2 overlap; denominator decision unrecorded. Owner session: D3-13 is a brief item; batch membership is defined over stage pool episodes and first release is WorkFirstReleased (SP spec §3.7) |
| Data export and as-of | FEAT-013 | Draft | Partial | #2461, #2574 | EX1/EX2 |
| Project groups and #3335 authorization | FEAT-005, PGRP-*, gates G-A..G-D, WP9, WP11 | Draft / handover plan | Partial | #2224 open (nurikarakaya; conflicting) | PM2; user-guide ownership wording |
| Application authority transition | #3335 M0–M8 | Approved (2 Oct) | Partial (dark) | many merged | Single evaluator; enforced mode |
| Architecture review (Oct 2026) | #3961; issues #3972–#3990 | Draft (PR only) | Phase 0 fixes merged (#3967, #3968, #3970, #3971) | #3961 (draft); #3966 parked | Persistence (#3985), events (#3973), flags (#3975), MassTransit (#3986), statistics (#3987); D1-02 |
| Feature-flag overhaul | P7 per-project targeting | Planning | Planned | — | R0 admission is its domain enrolment (PH-14) |
| Staged search import | #2612 | Plan (PR, docs only) | Planned | #2612 (mergeable, since 1 Sep) | X-IMPORT for P1/P2 |
| Notification inbox, study attention | flags notificationInbox, notificationEmail, studyAttention; reconciliationConversations (#3965) |
Draft (PR only) | Planned on main (code in open PRs; stack E2E never run in CI) |
#3932 → #3947 stack; #3965 (all re-checked unchanged on 5 October 2026) | RE4 (stage binding), BL1, VS1 (#3944; addressed in #3965, not yet merged), QY gap. Owner session: aliases become context-local under form or profile blinding; email content per D3-22 as amended; delivery remains unauthorised (notifications integration §7) |
| Keyword highlighting | FEAT-025 (duplicate ID) | In-Review | Verified, off | merged | — |
| Bulk update with study locks | ADR-020, FEAT-016 | Approved | Partial, flagged | merged | Every review write must honour locks |
| Reviewer no-work page redesign | #2412 | PR only | Planned | #2412 (conflicting) | Wording overlap with lifecycle |
The full per-feature notes (front matter, phases, file references) are in the sub-agent reports summarised here; the key document paths are linked from the integrated plan.
4. Open PRs in scope (live, 3 October 2026, about 04:52 BST; rechecked 05:48 BST)¶
Mergeability as GitHub reported it after recomputing against 2949ca3a7; the 05:48 recheck
found no change except #3955 merging. All authored by chrissena except #2224
(nurikarakaya).
Re-check, 5 October 2026 at 00:33 UTC (gh pr view, read-only), for the PRs this plan's joins
depend on: the notification stack #3932 to #3947 and #3965 are open with unchanged heads (#3932
conflicting, the rest mergeable); #3939 is conflicting and #3936 mergeable, both unchanged; #3746
is conflicting; #3742 is a draft; #3741 is a draft and now conflicting. Rows not named here were
not re-read. Owner-session note: no PR closure or disposition is authorised by the owner session
(G0-D4 to G0-D10 stay open).
| PR | State | Head | Notes |
|---|---|---|---|
| #3617 research (this package's worktree) | Merged on 3 October 2026 (f5318074d); conflicting at the first reading |
0f4c764b2 at the first reading |
5 committed files from 24 September at the first reading. The owner ledger, research inputs and this package were committed on the PR #3617 branch and merged to main on 3 October 2026 as a docs-only PR (D1-05, merge commit f5318074d) |
| #3964 ownership-transfer security fix | Merged 20:27 BST (19:27 UTC), merge commit 85e6facf7, after an approving Claude review on head 16788f9 and green checks; worktree and branches removed |
16788f9cb |
Kept by D1-01 (Chris, 3 October); ported #3969's active-member check and tests |
| #3969 duplicate ownership fix | Closed 19:27 UTC, with a comment pointing to #3964 | 9e4eaf36f |
Closed after the port (D1-01, decided by Chris on 3 October, carried out) |
| #3965 private reconciliation conversations | Open and ready for review; ten commits pushed (20:35 BST); local e2e journey passed (19:30 BST reading); the tenth commit makes the reconciler-reviewed-study refusal stage-independent | 986b1cdc2 |
Chris's Q-10 changes; stacked on #3947 (base codex/checked-pdf-proposals-and-explicit-administrator-a-r6bdl2) and waits for the stack; restack onto #3944 approved under D1-09 (3 October) if the stack owner agrees |
| #3546 AF2 tabs/Focus/action bar | Open, conflicting | b38dffbd3 |
Staging corrections 4–6 |
| #3543 branch tabs/delete/numbering | Open, mergeable (blocked) | 09684ba93 |
|
| #3394 Study fullscreen | Open, conflicting, stale (8 Sep) | aad2feca6 |
Superseded by the Focus contract |
| #3292 panel resizing | Open, conflicting, stale (6 Sep) | c71501d50 |
Chris chose Dockview instead |
| #3017 AF2 virtual scrolling | Open, conflicting, stale | 72ffc09cb |
|
| #3288 AF2 acceptance evidence | Draft, conflicting | d4fec9cc2 |
|
| #3939 progressive batches | Open, conflicting | 62e8101eb |
63 files |
| #3936 batches plan | Open, mergeable (blocked) | a799b538e |
|
| #3934 template import UI | Open, conflicting | 9d6c596cf |
Flag annotationQuestionImport |
| #2781 importer foundation | Open, conflicting | 2d8b071b0 |
Network writes disabled |
| #3932 → #3938 → #3941 → #3942 → #3943 → #3944 → #3945 → #3947 | Open, stacked, none merged; #3932 conflicting with main, the rest mergeable into their bases |
#3932 2ddd96fb0 · #3938 180f0d1bb · #3941 eb72c886d · #3942 75f89b33d · #3943 d75fd81b9 · #3944 59ab32e7b · #3945 25b364da3 · #3947 ae3c6749d |
Notification inbox, email, digests, reconciliation questions, study issues, PDF proposals; see notifications integration |
| #3955 QuestionAnswers stale scopes on transactional saves (fixes #3933) | Merged 04:47 UTC (c59d9d0f1) |
7cad12dc5 |
FEAT-024; touches the C7/C8 seams |
| #3956 reviewer screening drift guards (fixes #3937) | Merged 05:53 UTC | b0c18e033 |
FEAT-024; follow-up #3960 open |
| #3962 async point-fold slice 7 (docs, rules, status) | Merged 06:13 UTC | 5cca5e490 |
FEAT-024 STATUS still says "in review" and "fold flag off everywhere" |
| #3961 architecture review findings | Draft, mergeable | 3db9e5f6d |
Issues #3972–#3990; D1-02 |
| #2612 staged search import plan | Open, mergeable (docs only) | 03c4c57aa |
X-IMPORT |
| #3746 eligibility S6a | Open, conflicting | 66ec5a8e0 |
|
| #3742 eligibility S4-B | Draft, 0 files | 87c9de59f |
Migration tooling not started |
| #3741 eligibility S5 audit | Draft (conflicting at the 5 October 2026 re-check) | 22a5786cf |
Only source of the G1–G6 gap list |
| #3327 allocation preview acceptance | Open, conflicting, stale | 2c1055968 |
|
| #2224 custom project groups | Open, conflicting (22 Sep) | fff8385ac |
Author nurikarakaya; the authorization plan reuses its shape (D10), not the PR |
| #2412 reviewer no-work page redesign | Open, conflicting | 3feb4912c |
Not stage completion |
| #2387 QM child visualisation and assign tree | Open, conflicting | c81426c44 |
|
| #2461 QM v2 R1 umbrella | Draft, conflicting | 1ca9f5def |
738 files |
| #2572 → #2573 → #2574 → #2575 QM v2 stack | Open, dormant since April | af5136696 … 098330759 |
Harvest per Q-08 |
| #2987, #2986, #2629 (mergeable); #2812 (conflicting) | Open, dormant since 1 Sep | — | Schema/profile/response/validation inputs; #2986 harvest into R2a |
| #2621 profile versioning prototypes | Draft, conflicting, dormant | 105bdc09e |
Seven prototypes; its ADR numbers collide with main |
| #2469 stage overview chart refactor | Open, conflicting | 2488a1f92 |
Stage-target chart conflicts with SF2 |
Opened since the first read, outside this plan's areas: #3958 (integrated PDF viewer fixes) and
3959 (statistics test isolation).¶
Recently merged and relevant: statistics slices 0–6 (6a #3948 at 02:57 UTC and 6b #3949 at 03:39 UTC on 3 October) and #3955 (04:47 UTC); eligibility S1b, S2-C, S3, S4-A and the claim-revoked event; authorization M5b (#3929, #3921) and the catalogue coverage test (#3882); bulk update v2 and study locks (#3914,
3909); route-owned statistics SignalStores (#3776–#3795); Dockview fixes (#3828, #3734); design¶
parity (#3544, #3545, #3533, #3542).
5. Feature flags in scope¶
All default false unless stated. "Staging" and "Prod" are cluster-gitops values.yaml values
(runtime overrides not read). Production pilots need a per-flag decision with each owner (Q-25).
| Flag | Default | Hosts | Staging | Prod | E2E stack | Gates |
|---|---|---|---|---|---|---|
newQuestionManagement |
false | web | off | unset | — | New editor nav link only |
annotationFormV2 |
false | web | on | unset | — | AF2 form (whole environment) |
stageReviewRedesign |
false | web | unset | unset | — | Redesigned review shell |
stageReviewDockview |
false | web | unset | unset | — | Dockview workspace |
integratedPdfViewer |
false | web | on | unset | — | Integrated PDF viewer |
reviewEligibilityPolicy |
false | API only (PM only through #3939's PR-only block) | unset | unset | — | Eligibility code paths |
proportionalStudyAllocation |
false | API only | unset | unset | — | Allocation (on only in preview pr-3327) |
activeReviewerTrackingEnabled |
false | API, PM | unset | unset | true | Tracking (with signalRActive, default true); claims and capacity guards exist only when on |
maxInProgressSessions |
true (API appsettings), false (PM), false (preview) | API, PM | — | — | — | In-progress cap |
stagePermissionsConfig |
false | — | — | — | — | Mock stage-permissions UI |
disableMembership, editProjectMembers |
false | — | — | — | — | Membership controls |
syrfOwnedApplicationRoles(Enforced), delegatedWorkAdmissionEnforced |
false | — | — | — | — | Authority transition |
deletionLifecycle |
false | — | — | — | — | Message choice only today; gates creation of reversible deletion operations once built |
bulkStudyUpdateAtomicApply, batchRiskOfBiasAtomicApply |
false | — | — | — | — | Writers to inventory |
materializedProjectStatistics* (25) |
false | API, PM | 8 on for one pilot project, plus materializedProjectStatisticsFold pinned on (API and PM; "staging pilot only (Chris, 2026-10-01)") and partial fold coverage allowed on the API |
none | — | FEAT-024 |
materializedProjectStatisticsQuestionCounts |
false | — | — | — | — | Live question counts and locks |
screeningKeywordHighlighting, graph2Data, quantitativeDataExportEnabled |
false | — | — | quantitative export on in prod web | — | — |
notificationInbox, notificationEmail, studyAttention |
PR-only | API, web | — | — | — | Notification stack, environment-wide; accepted email continues after notificationEmail goes off |
reconciliationConversations |
PR-only (#3965) | API, web | — | — | — | Private conversations; depends on notificationInbox |
annotationQuestionImport |
PR-only | — | — | — | — | #3934 |
progressiveReviewBatches |
PR-only | API, PM, web | — | — | — | #3939; requires reviewEligibilityPolicy |
Flags proposed by the owner-session specifications (not in code; names are PROPOSALs).
contributionExclusion (default off; ACD spec §10), stageEligibilityTimeline (UI flag for the
eligibility explanation timeline; SP spec §10.1), pilotTimingTelemetry (default off, consent-based;
UX spec §10). deletionLifecycle above stays the flag for reversible project deletion, which the
owner session decided (D3-12 as amended). The PWA exploration has no flag and no build (UX spec §10).
6. Existing documents that conflict with later owner decisions¶
These need explicit supersession or amendment in the PR that implements the affected area. They are listed so nobody builds from them by mistake.
| Document / code | Conflicting statement | Superseded by | Handling in the plan |
|---|---|---|---|
| Review-eligibility policy D3a (In-Review, 25 Sep) | No stage closure or reopening state machine | RX2/LC1 (3 Oct), by the precedence rule | R3c introduces lifecycle for the new model; eligibility slices still don't. Record the supersession in the R3c ADR. |
Eligibility D3b and the AnnotationHasNoScreeningPrerequisite test |
Annotation never needs a screening decision | DP6/DP7 for configured dependencies. Owner session: step dependencies inside a stage only (Q-15 replaced) | Keep it as the behaviour of independent steps and of migrated legacy combined stages; add dependency semantics only where a step edge exists (C6, Q-24) |
| FEAT-008 stage filtering (and its user-guide draft) | Pass Included, Conflict forward; annotation pool = collective Included |
DP7 default (collective Include), DP6 within-stage own Include. Owner session: the stage study filter defines each stage's pool (Q-15 replaced); progression after one's own Include is the in-stage default and a stage setting can require collective Include (Q-01) | Amend in R3a (the FEAT-008 feature-doc input is in SP spec §13) |
| FEAT-010 stage settings | "Stages are unordered" (D30) | DP7 dependent stages. Owner session: the new model has no cross-stage order either, because each stage's filter defines its pool; D30 probably no longer conflicts (confirm in the R3a brief) | Amend in R3a |
| FEAT-026 batches README (PR) | "No arbitrary sequential stage-step model" | DP6 steps | Join at F3 with the batch owner |
| FEAT-006 reconciliation (README, design decisions, data-model migration, AF2 README) | Per-stage pools; "Annotator A vs B"; global anonymised-candidate invariant; answer every required question; single-annotator auto-promotion; rollback by $unset (D18) |
RE4, SF4/RE3, BL1, RE2, GS1; Q-29; canonical-aware rollback. Owner session: blinding owned by the form or profile, blinded by default, context-local aliases (OS-A02, OS-A03); target-one AutoAccept versus required human reconciliation (Q-29 decided-amended, OS-A28); completeness follows requiredness with a form override (Q-04) |
Amend in R4a |
| FEAT-009 screening annotations | Separate screening and extraction reconciliation workflows; per-field choice | RE4, RE2, RX1. Owner session: the reason-truncation bypass is read as a profile rule only for named must-agree reasons (RS spec §12, owner-visible) | Amend in R3b/R4p |
| QM v2 / annotation versioning | Per-stage question-set versions; checks against the previous version only; activation on stage enable; dataType versioned (D008) vs fixed (D38); one mutable pendingAnswer draft; gold as "latest version on the reconciliation annotation"; migration step 6 auto-promotion |
FV1–FV3, SF1, SL1, GS1, Q-29. Owner session: collaborative drafts with presence (OS-A01); the standard target versions the form (OS-A12) | Contract C4/C5 decide; harvest per Q-08 |
| FEAT-011 PRISMA (Approved) | Platform-wide MIG-11/MIG-12 backfill; ScreeningOutcome with one stageId and no legacy authority; $unset rollbacks; "Delete Study removes its Citations" |
Per-project adoption; per-profile outcome; canonical-aware rollback; reversible deletion. Owner session: per-project adoption becomes per-project conversion inside universal baseline waves (R4; OS-A15) | Amendments G–J (Q-06a) through the FEAT-011 change policy |
QM v2 PR-A OutcomeDataStateSnapshot |
GreaterIsWorse per row |
ODIR1 | C14 |
| #2621 ADR-013 | Rationale library shared across profiles | DP4 | Reference only |
| #2987 ADR-016 | "AnnotationProfile" bound to a stage | SF1; profile naming clash | C4 naming; disposition at G0 |
GroupedReviewConfiguration (#3732) |
Per-stage SessionCountTargetOverride |
SF2. Owner session: the standard target is part of the immutable form version, and Study-specific overrides have their own history; no step-level target override was approved (OS-A12) | Legacy-only; canonical stages take the form target, with an adapter for old readers (C7) |
| Category guidance per-stage override | Stage-owned guidance | SF1 (if it counts as form content) | Proposal A-15: keep as stage presentation text, never evidence |
| Live question locks (#3572–#3594) | Answered questions locked; additions only warned | FV1 | Canonical forms version instead of locking; legacy keeps locks |
User guide members-groups.md |
Administrators can assign a new owner | PM1/PM2 | Fix with the ownership enforcement follow-up |
Root CLAUDE.md domain model |
Describes versioning, profiles and screeningOutcomes[] as current |
— (accuracy) | Docs follow-up |
| FEAT-026 batches README (PR) | "Do not add a stage closure concept"; ConfigureProgressiveBatches requires a disabled stage |
LC1/RX2 (3 Oct) | R3c's Completed/Reopen lifecycle replaces "disable the stage before changing batches" for canonical stages |
FEAT-008 Filter Set model (JSON rules, same-profile $elemMatch simplifier) |
Undispositioned | DP6/DP7 routes. Owner session: the Filter Set becomes the stage study filter version schema v3; the circular-reference check becomes the no-recursion rule (SP spec §13) | Decide at F3 whether the Filter Set schema is the route representation; keep the simplifier as a correctness rule for screeningOutcomes[] filters |
docs/features/signalr-active-reviewer-tracking.md narrative (:102-160) |
Describes ActiveReviewSession |
The delivered SlotReservation and presence contract |
Presence owner's docs PR before F1a (T1) |
| ADR-014 (uncommitted) | Physical deletion of Project, Search and Study after a 24-hour grace period | Amendment J, QD1. Owner session: D3-12 decided-amended (O1 final clarification): ordinary project deletion is reversible; permanent erasure is unapproved (T-POL-01) |
D3-12; X-DEL. The ADR also needs a new number before it is committed (§1 item 17) |
| Owner session: owner ledger DP6/DP7 cross-stage routing and the access-policy proposal's "Incoming dependencies / progression between stages" | A next stage admits Studies through a personal or collective cross-stage route | Q-15 replaced by the stage study filter and step model (4 October 2026) | Annotate both documents as superseded (SP spec §13); no cross-stage progression setting exists |
| Owner session: owner ledger RA5 | "Does not change the normal form target" | Consolidation §1: an additional-review request raises the effective Study and form target | Overlay note in the ledger (RD spec §13) |
| Owner session: owner ledger BL1 and VS1 | BL1 stage-owned blinding; VS1 step policy with a stage default | Form or profile owns blinding (OS-A02); the form shows reconciled hints by default and a step may only hide them (OS-A04) | Overlay note in the ledger (RS spec §13) |
| Owner session: package text on account deletion (domain model, consistency model, migration, open questions) | Account deletion anonymises the Investigator record | D2-14 decided-amended: named attribution retained; identity erasure not decided (T-POL-02) |
Matches the code (§1 item 28); the package documents are amended by their owners |
| Owner session: the R4 research finding | Completed or archived projects may stay preserved legacy snapshots behind a read-only reader | Universal faithful baseline conversion after pilots (OS-A15) | BC spec; R6 becomes universal conversion waves, R7 the legacy-writer retirement milestone |
Owner session: docs/planning/screening-step-dependency-options.md |
Modes B and C as alternatives to the hybrid | Q-15 replaced | History only (§10) |
7. Observed defects and risks outside this plan's scope¶
Reported, not fixed (scope discipline). Each should become a follow-up issue Chris can triage.
| Finding | Evidence | Severity (proposed) |
|---|---|---|
Project administrators can transfer ownership through PATCH /api/projects/{id}; the owner-only ChangeOwner rule is never checked. The permission-update endpoints also accept owner-reserved activities. |
ProjectController.cs:365-390, 1303-1320; Project.cs:855-883; ResourceSecurity.json ChangeOwner; no use of ProjectChangeOwnerPolicy (re-verified; the permission-update part per review C) |
High (authorization); Chris approved the fix on 3 October: PR #3964, merged on 3 October (85e6facf7) |
| Question deletion destroys every answer non-atomically | ProjectManagementService.cs:201-222; #3088 |
High (data loss), known. Under the new versioning a published question can never be permanently deleted (QD1, Chris, 3 October); legacy projects keep today's deletion until adopted |
| Reconciliation responses include every session on the study across stages; reviewer identities likely included | ReviewController.cs:1586-1628; StudyDto.cs:53-58; agent: StatsWithIncompleteDto.cs:14-31 |
Medium (privacy); current UI shows no names |
| Export page lets any ExportData holder unmask identities regardless of stage blinding | Review C: blinding-option-group.component.html:6-24; ResourceSecurity.json ExportData |
Medium (privacy) |
Membership route guard checks project.editMembership (typo) |
project-admin.routes.ts:36; authorization WP1d |
Low to medium (UI guard only; likely a no-op; server checks EditMemberships) |
| Required answers are not enforced on the server | AnnotationQuestion.cs:55, 227 |
Medium (relies on client) |
| Debug text "Focused question" ships in the new Design tab | design.component.html:14 |
Low |
| The export option "completed sessions only" is forwarded but never applied by the writers, so exports can include incomplete work | WriterConfig.cs:46-60; screening research §1.5 |
Medium (export correctness) |
COMPARISON.md line 107 says Review Prototype v4 is absent; it exists in handover/2026-09-21-stage-review-design/design_handoff_stage_review_page/ |
Prototype asset search | Low (documentation) |
| Stale status documents: AF2 STATUS, FEAT-024 STATUS, allocation STATUS, the catalogue, root CLAUDE.md domain model | Theme A/B reports | Low |
Duplicate identifiers: FEAT-025 (allocation and keyword highlighting), ADR-008 (two documents); every ADR number in open QM/annotation PRs collides with main (next free: ADR-021) |
Theme A/B reports. Re-checked 5 October 2026: ADR-021 is still the next free number; the uncommitted deletion ADR also claims the taken ADR-014 (§1 item 17) | Low (process) |
Broken references: .planning/REQUIREMENTS.md, docs/features/annotation-management-reconciliation/… |
Theme A/B reports | Low |
The owner decision ledger, later research and this package are committed only on the PR #3617 branch (latest planning commit aac4debcd), not yet on main |
git ls-files on the PR #3617 branch; aac4debcd is not an ancestor of origin/main |
Medium (authority at risk until merged to main; resolved: PR #3617 merged to main on 3 October 2026, f5318074d) |
| Production has no claims or capacity guards because tracking is off everywhere; the over-allocation report #2446 remains open | FeatureFlags.cs:35-36; cluster-gitops values; #2446 |
Medium (capacity correctness) |
| Reconciliation has no editor exclusion: two reconcilers can edit one study | StageReviewService.cs:67-70, 153 |
Medium (data correctness) |
| Presence snapshots name claim holders to every member who can view studies, whatever the blinding | StudyReviewPresenceSnapshot.cs:86-96 (per review RT); #3892 |
Medium (privacy; dark today) |
reviewEligibilityPolicy and proportionalStudyAllocation reach the API host only, while Core code reading them runs in both hosts |
env-mapping.yaml services: [api] block |
Medium (split brain on enablement) |
| The allocation flag is read twice per request (runtime value in the controller, process value in admission) | ReviewController.cs:500, 626, 753, 790, 1173, 1443, 1609; StudyRepository.ActivityReservations.cs:19-21 (per review AP) |
Low (latent; real once overrides work) |
The question-delete cascade and the inclusion recalculation change pmStudy without bumping Audit.Version |
StudyRepository.cs:1306-1319, 1620-1650 |
Medium (CAS cannot see them; #3985) |
| Stale status documents: allocation STATUS (#3603), FEAT-024 STATUS (slice 7, staging fold flag) | proportional-study-allocation/STATUS.md:71; materialized-project-statistics/STATUS.md:372-386 |
Low |
Owner session: DELETE api/account/profile accepts removePersonalData and never reads it, so a caller may believe personal data was removed |
AccountController.cs:240 (signature only); generated client api-client.generated.ts:869-874; §1 item 28 |
Low (misleading contract); the D2-14 decision keeps named attribution, and any wording that promises removal needs legal review (ACD spec §12.3) |
Owner session: the web manifest is not linked from index.html, is probably not copied into the build, has empty names and points at icon paths that do not exist in the build |
src/services/web/src/site.webmanifest; src/index.html; angular.json assets; §1 item 27 |
Low (inert metadata); input to the non-MVP PWA exploration, not a defect fix to schedule now |
Owner session: the uncommitted deletion ADR is numbered ADR-014, which main already uses for the integrated PDF viewer |
.worktrees/bulk-pdf-deletion-lifecycle (?? in git status); docs/decisions/ADR-014-integrated-study-pdf-viewer.md; §1 item 17 |
Low (process); renumber when committed (ADR-022 is free; #3961 took ADR-021 on 5 October 2026) |
8. Prototype and design assets¶
See the UI coverage comparison, which records every asset found and not found. Owner session: the SHA-256 digests of the v10 prototype files were re-computed on 5 October 2026 and match the recorded values (UI comparison §1). The design-prototype handoff is the self-contained input for the next design iteration of SyRF Prototype v10 (OS-A30); no design session is messaged and no new prototype is built by this package.
9. Notification infrastructure¶
See notifications integration. Owner session: the communication decisions (D3-22, D3-24, D3-25 decided; D3-21, D3-23 brief items) are in notifications integration §7; delivery remains unauthorised.
10. Earlier-year documents and their disposition (PROPOSAL)¶
Review A listed earlier documents the first draft didn't reference. Status and dates from their front matter.
| Document | Status, date | Disposition |
|---|---|---|
docs/planning/screening-step-dependency-options.md (PR3617 worktree) |
Draft, 24 Sep | Input to Q-15: its Modes B and C are now presented alongside the hybrid. Owner session: Q-15 is replaced by the stage study filter and step model; this document is history only |
docs/planning/active-reviewer-tracking-overhaul.md |
Approved, 10 Apr | Background for C7 claims (E18); implemented behind activeReviewerTrackingEnabled |
docs/planning/review-access-state-overhaul.md |
Draft, 17 Apr | Background for C6 admission; superseded in scope by the eligibility programme; read before F3 |
docs/planning/session-capacity-suspended-sessions-handover.md |
Draft, 15 Apr | Background for capacity and suspended-session behaviour in C7 (E6, E18); read before F1a |
docs/planning/session-copy-review.md |
Draft, 17 Apr | Input to the terminology and copy contract (C17) |
docs/planning/data-export-analysis.md |
Draft, 11 Mar | Input to C11 export modes and the OnlyCompleted fix |
docs/planning/stage-review-layouts/contract.md |
Approved (layout contract) | Binding for C17's layout amendment |