Worklist enhancements: Procedure Requested/Performed + per-status review history

1. Overview

Enhance the study-reviewer worklist so each work item carries a structured Requested Procedure (what the requester wants assessed) and Performed Procedure (what the reviewer actually did), and so that every status transition — not just rejection — can carry a reviewer note. The full arc (requested → status changes + notes → performed) is surfaced as a chronological history in the Study Details drawer.

Naming and structure track the DICOM Requested Procedure module and Performed Procedure Step (MPPS / UPS) attributes, consistent with the plugin's existing habit of mirroring DICOM. No new DB schema — all state lives in the work item's existing orthanc JSONB (already round-tripped to clients as Meta).

Chain: builds on the now-closed study-review UI design study oak-tree/medical-imaging/ohif-viewers#73.

2. Problem & rationale

Today a worklist request is effectively "please look at this," and the reviewer marks it complete. Two gaps:

  • No requested-vs-performed record. There's no structured statement of what assessment was asked for, nor of what the reviewer actually did — only an opaque status flip. Thin for clinical accountability and useless for downstream analytics.
  • Notes only on rejection. Reviewers can explain a rejection but cannot annotate an approval, an in-progress hand-off, or a completion ("confirmed landmarks, alignment within spec"). The reasoning behind most state changes is lost.

3. Business value

  • Clinical accountability & quality. A first-class requested/performed pair makes each review self-documenting — who asked for what, who did what, and why — the substrate for reviewer QA, second-read programs, and discrepancy tracking.
  • Audit & regulatory posture. A per-transition history with attributable notes advances the review/approval evidence regulated customers expect (a step toward the open SN MS2 "audit logs and compliance hooks" item — see §7).
  • Agentic-AI enablement. The requested/performed split is exactly the contract an AI reviewer needs: read the Requested Procedure, act, write back a Performed Procedure + note. Aligns with oak-tree/medical-imaging/imaging-development-env#94.
  • Interoperability & integration. Modeling on DICOM MWL Requested Procedure and MPPS Performed Procedure Step shortens the path to RIS/order-system integration and keeps the data speakable in standard terms.
  • Commercial differentiation. "Structured, coded, auditable review workflow" is a credible enterprise-imaging talking point versus open viewers that only toggle a status flag.

Success indicators: % of completed work items carrying a performed procedure; % of transitions with an attached note; ability to answer "what was requested vs. done" for any study without leaving the drawer.

4. Concepts

4.1 Requested Procedure

The clinical ask captured when a study is placed on a worklist. Mirrors the DICOM Requested Procedure module: a coded Requested Procedure Code Sequence (0032,1064) and/or a free-text Requested Procedure Description (0032,1060), with optional Requested Procedure Priority (0040,1003) and Reason for the Requested Procedure (0040,1002). Coded concepts use the DICOM Code Sequence Macro (Code Value / Coding Scheme Designator / Code Meaning), sourced from the group's existing ImagingTag library.

4.2 Performed Procedure

What the reviewer actually did, captured as the item advances/completes. Mirrors the DICOM Performed Procedure Step: a coded Procedure Code Sequence (0008,1032) and/or a free-text Performed Procedure Step Description (0040,0254), with optional Performed Procedure Step Status (0040,0252) and start/end timestamps (0040,0244/0245) / (0040,0250/0251).

5. Technical requirements

Functional

  • FR-1 — Requested Procedure capture. On "Request Review," allow an optional Requested Procedure (coded sequence and/or description, optional priority/reason).
  • FR-2 — Performed Procedure capture. On any reviewer update (typically completion), allow an optional Performed Procedure (coded sequence and/or description).
  • FR-3 — Optional procedure description (explicit). Each procedure facet accepts a free-text description independently of coded concepts. A facet is valid if it has at least one of {coded concept, description}; neither is individually mandatory and both may be supplied. Description-only and code-only procedures are both first-class.
  • FR-4 — Note on every transition. Allow an optional free-text note on any status change (not only Rejected), persisted via the existing Comment path and linked to that transition.
  • FR-5 — Status history. Record an entry on item creation and on every state change: previous state, new state, actor, timestamp, linked note (if any).
  • FR-6 — Unified history retrieval. The merged chronological history (transitions + procedures + comments) is retrievable by clients from the worklist item's Meta plus the existing comments API, gated by existing ACL. (A dedicated server endpoint is deferred to #55.)
  • FR-7 — Namespace integrity. Prevent clients from forging or overwriting server-owned procedure/history attributes via the general Meta channel.

Non-functional

  • NFR-1 — No schema change. Pure orthanc JSONB; no columns, tables, or migration.
  • NFR-2 — DICOM alignment. Attribute keys and structure mirror the Requested Procedure module, Performed Procedure Step, and Code Sequence Macro (see §6.2).
  • NFR-3 — Backward compatible. Absence of procedure/history is valid; existing worklist clients unaffected.
  • NFR-4 — Audit caveat. JSONB history is mutable (not tamper-evident); designed to be promotable to an append-only store later without changing the client contract.
  • NFR-5 — ACL parity with the rest of the drawer.

6. System specification

6.1 Storage model

Three reserved, server-owned keys inside the work item's orthanc JSONB (surfaced inside Meta): RequestedProcedure, PerformedProcedure, ReviewHistory.

orthanc = {
  // ...free-form client Meta (reserved keys below are server-owned)...
  "RequestedProcedure": {
    "RequestedProcedureID": "RP-00123",                        // (0040,1001) SH, optional
    "RequestedProcedureDescription": "Review TKA alignment",   // (0032,1060) LO, optional free text
    "RequestedProcedureCodeSequence": [                        // (0032,1064) SQ
      { "CodeValue": "P5-12345", "CodingSchemeDesignator": "SRT", "CodeMeaning": "TKA plan review" }
    ],
    "RequestedProcedurePriority": "ROUTINE",                   // (0040,1003) SH, optional
    "ReasonForTheRequestedProcedure": "Pre-op planning",       // (0040,1002) LO, optional
    "RequestedBy": 222, "RequestedDateTime": "<iso>"           // plugin metadata
  },
  "PerformedProcedure": {
    "PerformedProcedureStepID": "PPS-00123",                   // (0040,0253) SH, optional
    "PerformedProcedureStepDescription": "Confirmed femoral/tibial landmarks", // (0040,0254) LO, optional free text
    "ProcedureCodeSequence": [                                 // (0008,1032) SQ
      { "CodeValue": "P5-12346", "CodingSchemeDesignator": "SRT", "CodeMeaning": "Landmark verification" }
    ],
    "PerformedProcedureStepStatus": "COMPLETED",               // (0040,0252) CS, optional
    "PerformedProcedureStepStartDateTime": "<iso>",            // (0040,0244)+(0040,0245)
    "PerformedProcedureStepEndDateTime": "<iso>",              // (0040,0250)+(0040,0251)
    "PerformedBy": 222
  },
  "ReviewHistory": [                                           // plugin construct; echoes worklist `State`
    { "PreviousState": "scheduled", "State": "in-progress", "User": 222, "Timestamp": "<iso>", "CommentUID": null },
    { "PreviousState": "in-progress", "State": "completed", "User": 222, "Timestamp": "<iso>", "CommentUID": "<uuid>" }
  ]
}

6.2 Attribute → DICOM tag mapping

JSON key DICOM attribute Tag VR
RequestedProcedureID Requested Procedure ID (0040,1001) SH
RequestedProcedureDescription Requested Procedure Description (0032,1060) LO
RequestedProcedureCodeSequence Requested Procedure Code Sequence (0032,1064) SQ
RequestedProcedurePriority Requested Procedure Priority (0040,1003) SH
ReasonForTheRequestedProcedure Reason for the Requested Procedure (0040,1002) LO
PerformedProcedureStepID Performed Procedure Step ID (0040,0253) SH
PerformedProcedureStepDescription Performed Procedure Step Description (0040,0254) LO
ProcedureCodeSequence Procedure Code Sequence (0008,1032) SQ
PerformedProtocolCodeSequence Performed Protocol Code Sequence (0040,0260) SQ
PerformedProcedureStepStatus Performed Procedure Step Status (0040,0252) CS
PerformedProcedureStepStartDateTime PPS Start Date / Time (0040,0244)/(0040,0245) DA/TM
PerformedProcedureStepEndDateTime PPS End Date / Time (0040,0250)/(0040,0251) DA/TM

Code Sequence Macro item (used by every *CodeSequence), with mapping to the existing ImagingTag columns:

JSON key DICOM attribute Tag ImagingTag field
CodeValue Code Value (0008,0100) value
CodingSchemeDesignator Coding Scheme Designator (0008,0102) scheme_designator
CodingSchemeVersion Coding Scheme Version (0008,0103) scheme_version
CodeMeaning Code Meaning (0008,0104) meaning

6.3 Request/response contract

Worklist create/update accepts an optional Procedure block alongside the existing State, Meta, and Comment:

PUT .../studies/{id}/worklist/{wid}
{
  "State": "completed",
  "Comment": { "Text": "Reviewed; alignment within spec." },   // optional, existing path
  "Procedure": {
    "PerformedProcedure": {
      "ProcedureCodeSequence": [ { "CodeValue": "P5-12346", "CodingSchemeDesignator": "SRT", "CodeMeaning": "Landmark verification" } ],
      "PerformedProcedureStepDescription": "Confirmed femoral/tibial landmarks."
    }
  }
}

On create, the Procedure block normally carries only RequestedProcedure. Because orthanc already serializes to clients as Meta, the reserved keys ride along in the standard worklist response — no serializer change.

6.4 Namespace protection

The worklist form maps inbound Metaorthanc, so a client could otherwise overwrite the reserved keys. The server strips RequestedProcedure / PerformedProcedure / ReviewHistory from any inbound Meta and re-applies the server-owned values; procedure writes come only through the validated Procedure block.

6.5 History timeline retrieval

Clients assemble the timeline client-side from the worklist item's Meta (reserved keys ReviewHistory, RequestedProcedure, PerformedProcedure) merged with the existing comments API, gated by existing ACL. A dedicated server-side endpoint (GET .../studies/{id}/history) is deferred to #55 and is out of scope for this issue.

7. Design decision & trade-offs (locked 2026-06-29: pure orthanc JSONB)

No new columns/tables/migration. Trade-offs accepted: last-write-wins on the blob; mutable, non-append-only history (so this does not by itself satisfy the SN MS2 audit-log item). ReviewHistory is shaped so it can be promoted to a dedicated append-only table later without changing the client/Meta contract. The existing ProcedureStep table is intentionally left unused.

8. Implementation checklist

Server (oak-tree/medical-imaging/orthanc-sonador)

  • Validate the optional Procedure block (RequestedProcedure / PerformedProcedure; coded sequence and/or description per FR-3) — !54 (merged)
  • Write procedures into the RequestedProcedure / PerformedProcedure reserved keys (no columns) — !54 (merged)
  • Append a ReviewHistory entry on create and on every status transition, with optional CommentUID!54 (merged)
  • Strip/re-apply reserved keys to protect them from client Meta overwrites (FR-7) — !54 (merged)
  • Fix latent NameError in WorklistItemValidationForm.clean() (reads state before assignment) — !54 (merged)
  • Redact the copied "Performed Procedure step" docstring noted in oak-tree/medical-imaging/orthanc-sonador#41!54 (merged)

Client (oak-tree/medical-imaging/ohif-viewers — stand-alone web app; all worklist UI under platform/viewer/src/. Scope note: agent work is limited to this repo and the server repo; do not modify other repositories or submodule pins — downstream integration into the Sonador web application is handled manually.)

  • Create Worklist Item dialog: capture "Reason for Review" (free text, stored as RequestedProcedure.ReasonForTheRequestedProcedure) and optional RequestedProcedureDescription. Coded-concept entry (ImagingTag-backed picker) is out of scope for this issue.oak-tree/medical-imaging/ohif-viewers!58
  • Rapid Review Toolbar: note input on every status change — optional for all transitions, required for Cancelled (existing behavior unchanged); capture Performed Procedure (description) on completion — oak-tree/medical-imaging/ohif-viewers!58
  • Details Drawer: render the unified history timeline (available client-side via Meta) — deferred pending a design round: the timeline component and Meta/comments data plumbing landed in oak-tree/medical-imaging/ohif-viewers!58 (StudyItemExpandedNG/components/ReviewHistory) but are intentionally not rendered; a three-column drawer proved unusable for history-heavy studies

Testing (per oak-tree/medical-imaging/imaging-development-env#87) — implemented in oak-tree/medical-imaging/sonador-ftests!10 (tests_ext_worklist_procedures)

  • Unit: procedure validation incl. description-only and code-only facets (FR-3) — covered at the API level: acceptance (test_procedure_facets_description_or_code) and rejection paths (test_procedure_validation_rejected)
  • Integration: one ReviewHistory entry per transition; note links via CommentUID; reserved keys survive a client Meta update (FR-7); completed/cancelled stay locked; timeline ordering + ACL denial — test_meta_reserved_keys_protected, test_cancelled_with_note_locked, test_comment_only_update_appends_history, test_history_acl_parity
  • Functional arc: request (with Requested Procedure) → process → complete (with Performed Procedure + note) → history timeline via Metatest_review_history_full_arc (+ DICOMweb variant)
  • Predecessor design study (closed): oak-tree/medical-imaging/ohif-viewers#73
  • Workflow concept: oak-tree/medical-imaging/imaging-development-env#46
  • Study-list status API: oak-tree/medical-imaging/imaging-development-env#74, oak-tree/medical-imaging/imaging-development-env#75
  • Agentic-AI review loop: oak-tree/medical-imaging/imaging-development-env#94
  • Worklist testing plan: oak-tree/medical-imaging/imaging-development-env#87
  • Foundational worklist API: oak-tree/medical-imaging/orthanc-sonador#19
  • Docstring cleanup: oak-tree/medical-imaging/orthanc-sonador#41

10. Milestone

Assigned to Sonador Studylist UI Refinements Round 2. Intentionally not part of Secure Resource Sharing & Worklists (SN MS2) — that milestone is being closed out, not expanded.

Edited by Sonador Claude