Skip to content

v6.2 Flexible Phase 1 — SOP Contract Spec

Status: PR-1.1 shipped (2026-06-02) — §2 (schema migration) complete.

1. Context

The v6.1 pipeline audit (docs/audits/v6.1-pipeline-2026-06-02/) surfaced that the current SOP YAML schema is flat-layered with must_collect lists per layer, making it hard to: - Express per-field matching vs safety semantics - Attach document interpretation schemas for Phase 4 grounding - Add addendum pointers and verbal acknowledgement rules

v6.2 Phase 1 introduces a richer schema alongside the existing fields for incremental Phase 2 wiring.

2. New SOP Schema — SHIPPED in PR-1.1

The following worked example shows the BEFORE/AFTER for tkr.yaml.

BEFORE (v6.1 schema, layer-centric)

id: tkr
procedure_codes: [...]
data_source: fabricated_pending_naidu_review_2026_05_22
clinical_review: ...
layers:
  - id: mobility_conditioning
    priority: 1
    must_collect: [primary_complaint, affected_side, ...]
  - id: comorbidities_meds
    priority: 4
    must_collect: [comorbidities, medications, ...]
faq: [...]

AFTER (v6.2 schema, dual-schema transitional)

sop_id: tkr           # NEW: canonical v6.2 id
id: tkr               # PRESERVED: backward compat for sop_loader.py
procedure_codes: [...] # PRESERVED: unchanged

required_data:        # NEW: flat list replaces layered must_collect
  - name: primary_complaint
    mandatory_for_matching: true
    mandatory_for_safety: false
    source_hints: [extracted]
  - name: comorbidities
    mandatory_for_matching: false
    mandatory_for_safety: true
    source_hints: [conversational, extracted]
  # ... all fields from all layers, deduplicated

required_documents:   # NEW: structured doc requirements
  - type: imaging
    mandatory: true
    interpretation_schema: {}  # Phase 4 populates
    ttl_seconds: 300

clinical_safety_rules: []  # Phase 2 populates from clinical_rules
addendum_pointers: []       # Phase 2 populates
verbal_acknowledgement_rules: []  # Phase 4 populates

faqs: [...]           # NEW alias for faq (preserved for compat)

# Legacy fields preserved (sop_loader.py reads these):
data_source: fabricated_pending_naidu_review_2026_05_22
clinical_review: ...
layers: [...]         # PRESERVED: sop_loader.py still reads layers
faq: [...]            # PRESERVED: sop_loader.py still reads faq

Schema delta summary

Old field New field Action
id sop_id Added alias; id preserved
layers[].must_collect required_data[] Flattened + enriched; layers preserved
bare string doc lists required_documents[] Structured; mandatory=true, ttl_seconds=300
clinical_rules[] (where present) clinical_safety_rules[] Mapped; blocking inferred from text
addendum_pointers Added empty (Phase 2)
verbal_acknowledgement_rules Added empty (Phase 4)
faq faqs Added alias; faq preserved

TKR + ACL interpretation_schema (Phase 4 preview)

TKR knee_xray:

joint_space_mm: float
osteophyte_grade: int
malalignment_deg: float

TKR bloodwork_recent:

hba1c: float
hgb: float
creatinine: float
recency_days: int

ACL knee_mri:

acl_tear_grade: int
meniscal_involvement: bool
bone_bruise_present: bool

3. Migration implementation

  • Script: scripts/migrate_sop_schema_v6_2.py
  • Schema validator: app/services/sop_schema_v6_2.py (Pydantic)
  • Tests: tests/test_sop_schema_v6_2.py (18 SOPs × 4 assertions = 72 cases)
  • SOPs migrated: all 18 in config/prompts/sops/
  • Backward compat: sop_loader.py unchanged; reads id, layers, faq which are preserved

4. Phase 2 (not yet wired)

Phase 2 will: - Add a new sop_reader_v6_2.py that reads required_data instead of layers - Wire required_data into the completeness calculator - Populate addendum_pointers for financial/insurance triggers - Remove layers from the YAML once Phase 2 reader is stable

5. Phase 4 (not yet wired)

Phase 4 will: - Populate required_documents[].interpretation_schema for all 18 SOPs - Add verbal_acknowledgement_rules for grave-disclosure scenarios - Integrate with the document grounding pipeline