Sandbox/ModelFork: Difference between revisions
From OHC Network Wiki
More languages
More actions
Content deleted Content added
Automated edit (via create-page on MediaWiki MCP Server) |
Automated edit (via update-page on MediaWiki MCP Server) |
||
| Line 1: | Line 1: | ||
{{Doc header |
{{Doc header |
||
|type=guide |
|type=guide |
||
|domain=platform |
|||
|title=Model Forking Demo |
|title=Model Forking Demo |
||
|order=999 |
|order=999 |
||
Latest revision as of 10:50, 6 July 2026
Older versions: Sandbox/ModelFork/DevEntity/PatientModel/1.0.0
ℹ️ Sandbox demonstration
This page demonstrates a model forking (branching) workflow using the wiki's copy-on-write versioning and Cargo/SMW stack. While the version demo shows time-based evolution, this demo shows parallel forks maintained by different entities with an upstream/downstream sync relationship.
The problem
When multiple organizations adopt a shared data model:
- They need custom fields for their specific workflows
- They can't be forced to accept every upstream change immediately
- They need to cherry-pick which upstream changes to adopt
- The upstream needs to evolve without breaking downstream consumers
This is the same problem git branches solve in source code — applied to data model governance.
The forking workflow
| Step | What happens |
|---|---|
| 1. Publish | The development entity publishes the canonical model (single source of truth). |
| 2. Fork | A production entity copies the model at a specific version and begins maintaining its own fork. |
| 3. Diverge | Both sides evolve independently. The dev entity adds/removes/renames fields rapidly. The prod entity adds its own custom fields. |
| 4. Sync | The prod entity chooses to pull in upstream changes — deciding per-field whether to adopt, adapt, or decline. |
| 5. Repeat | This is a continuous cycle, not a one-time migration. |
The models
Upstream (source of truth)
- DevEntity PatientModel (latest — v2.0.0)
- DevEntity PatientModel v1.0.0 (frozen snapshot — copy-on-write fork)
Downstream (production forks)
- AcmeCare PatientModel — Forked from Dev v1.0.0, added insurance + physician fields
Key differences from versioning
| Dimension | Versioning (demo) | Forking (this demo) |
|---|---|---|
| Axis | Time (1.0 → 2.0 → 3.0) | Space (Dev ← Prod₁, Dev ← Prod₂) |
| Ownership | Single entity | Multiple independent entities |
| Divergence | Accumulates, rarely removes | Can diverge significantly |
| Sync | Not applicable | Selective cherry-pick from upstream |
| Copy-on-write | Version freeze → subpage | Fork creation → subpage |
Structured field data
Every model below stores its fields in the ModelField Cargo table. This query shows all fields across all forks:
| Model | Field | FieldType | Notes |
|---|---|---|---|
| PatientModel_AcmeCare | address | Text | Inherited from upstream v1.0.0 |
| PatientModel_AcmeCare | date_of_birth | Date | Inherited from upstream v1.0.0 |
| PatientModel_AcmeCare | String(254) | Inherited from upstream v1.0.0 | |
| PatientModel_AcmeCare | first_name | String(100) | Inherited from upstream v1.0.0 |
| PatientModel_AcmeCare | gender | String(1) | '''Kept''' — upstream removed in v2.0.0; AcmeCare still requires it |
| PatientModel_AcmeCare | insurance_id | String(50) | '''Custom''' — AcmeCare-specific |
| PatientModel_AcmeCare | insurance_provider | String(100) | '''Custom''' — AcmeCare-specific |
| PatientModel_AcmeCare | last_name | String(100) | Inherited from upstream v1.0.0 |
| PatientModel_AcmeCare | patient_id | UUID | Inherited from upstream v1.0.0 |
| PatientModel_AcmeCare | phone | String(20) | '''Kept as optional''' — upstream made required in v2.0.0 |
| PatientModel_AcmeCare | primary_care_physician | String(100) | '''Custom''' — AcmeCare-specific |
| PatientModel_DevEntity_v1 | address | Text | Optional — free-text address |
| PatientModel_DevEntity_v1 | date_of_birth | Date | Required — ISO 8601 format (YYYY-MM-DD) |
| PatientModel_DevEntity_v1 | String(254) | Optional | |
| PatientModel_DevEntity_v1 | first_name | String(100) | Required — patient's given name |
| PatientModel_DevEntity_v1 | gender | String(1) | Optional — M / F / O; removed in v2.0.0 |
| PatientModel_DevEntity_v1 | last_name | String(100) | Required — patient's family name |
| PatientModel_DevEntity_v1 | patient_id | UUID | Required — system identifier, auto-generated |
| PatientModel_DevEntity_v1 | phone | String(20) | Optional in v1.0.0 — upgraded to required in v2.0.0 |
| PatientModel_DevEntity_v2 | address | Text | Optional — free-text address |
| PatientModel_DevEntity_v2 | blood_type | String(5) | Optional — NEW in v2.0.0; A+, A-, B+, B-, AB+, AB-, O+, O- |
| PatientModel_DevEntity_v2 | date_of_birth | Date | Required — ISO 8601 format (YYYY-MM-DD) |
| PatientModel_DevEntity_v2 | String(254) | Optional | |
| PatientModel_DevEntity_v2 | first_name | String(100) | Required — patient's given name |
| PatientModel_DevEntity_v2 | last_name | String(100) | Required — patient's family name |
| PatientModel_DevEntity_v2 | patient_id | UUID | Required — system identifier, auto-generated |
| PatientModel_DevEntity_v2 | phone | String(20) | Required (was optional in v1.0.0) |
| PatientModel_DevEntity_v2 | preferred_language | String(50) | Optional — NEW in v2.0.0; ISO 639-1 code |