Well Reopening Scoring Schema And Worklist Design

Source: docs/architecture/WELL_REOPENING_SCORING_SCHEMA_AND_WORKLIST.md

Manual Index Client UI

Well Reopening Scoring Schema And Worklist Design

Purpose

This document turns the reopening-target ranking logic into three concrete artifacts:

  1. an exact PostgreSQL scoring schema,
  2. a JSON output contract for ranked reopening targets,
  3. a UI design for the scientist and engineer worklist.

The goal is to separate:

  1. historic bypassed-pay discovery,
  2. remaining-payload assessment,
  3. actual reopening target selection.

Those are related, but they are not the same workflow.

Why A Separate Reopening Layer Is Needed

ops.well_bypassed_candidates is useful for interval discovery.

It is not enough for reopening decisions because reopening decisions require:

  1. dynamic depletion assessment,
  2. operability assessment,
  3. score breakdown transparency,
  4. ranking across many wells in one reservoir,
  5. gating by critical gaps and evidence completeness.

That is why reopening ranking belongs in a distinct layer.

High-Level Architecture

flowchart TD A["Normalized Well Logs"] --> B["Pay Event Builder"] B --> C["Bypassed-Pay Candidate Builder"] C --> D["Reopening Scoring Engine"] E["Production + Injection History"] --> D F["Completion / Workover History"] --> D G["Well Integrity / Operability"] --> D H["Gap Engine"] --> D I["Evidence Pack"] --> D D --> J["Reopening Target Table"] J --> K["Scientist / Engineer Worklist"] J --> L["Portfolio JSON Output"] J --> M["2D / 3D Context Panels"]

Scoring Model

The reopening score should be a weighted blend of:

  1. static_score
  2. dynamic_score
  3. operability_score
  4. confidence_score

Default weighting

\[

Score_{total} =

0.35(Score_{static}) +

0.30(Score_{dynamic}) +

0.20(Score_{operability}) +

0.15(Score_{confidence})

\]

Score intent

static_score

Measures original subsurface quality.

Inputs:

  1. Vsh
  2. PHIE
  3. Rt
  4. Sw
  5. net pay
  6. gross thickness
  7. structural position

dynamic_score

Measures remaining payload likelihood now.

Inputs:

  1. cumulative production
  2. water cut trend
  3. pressure support or depletion
  4. offset drainage
  5. injector influence
  6. unswept potential

operability_score

Measures whether the well is practical to reopen.

Inputs:

  1. casing/integrity
  2. workover complexity
  3. completion readiness
  4. access
  5. cost risk

confidence_score

Measures whether the data is good enough to trust.

Inputs:

  1. log quality
  2. CRS confidence
  3. depth-reference confidence
  4. completion data completeness
  5. production/injection data completeness
  6. evidence pack completeness

PostgreSQL Scoring Schema

This design is implemented in:

1. ops.reopen_score_profiles

This stores reusable scoring profiles.

Purpose:

  1. keep weights versioned,
  2. keep Archie defaults explicit,
  3. keep gating rules auditable,
  4. let projects evolve scoring without changing code first.

Core columns:

  1. scoring_profile_id
  2. project_id
  3. profile_key
  4. display_name
  5. weights
  6. archie_defaults
  7. gating_rules
  8. scoring_version
  9. is_active

2. ops.well_reopening_targets

This is the new ranked worklist output table.

Purpose:

  1. one row per ranked reopening target,
  2. trace back to bypassed-pay candidate when available,
  3. expose score components and decision gates,
  4. support portfolio ranking and UI filtering.

Core columns:

  1. reopening_target_id
  2. project_id
  3. well_id
  4. source_candidate_id
  5. source_interpretation_id
  6. scoring_profile_id
  7. target_rank
  8. static_score
  9. dynamic_score
  10. operability_score
  11. confidence_score
  12. total_score
  13. classification
  14. blocking_reason
  15. recommended_action
  16. historic_payload_class
  17. remaining_payload_class
  18. depletion_risk
  19. operability_status
  20. data_confidence
  21. score_inputs
  22. assumptions_json
  23. rw_value
  24. rw_source
  25. a_factor
  26. m_exponent
  27. n_exponent
  28. sw_model
  29. sw_confidence
  30. evidence_pack_id
  31. scoring_version

3. ops.well_data_gaps extension

The migration also adds:

  1. gap_domain
  2. promotion_action

This is necessary because scoring must distinguish:

  1. non-blocking warnings,
  2. review holds,
  3. spatial-only quarantine,
  4. full decision-grade block.

Reopening Classification

Use the following operational classes:

  1. A
  1. B
  1. C
  1. D
  1. Q

Gating Rules

No target should be promoted without gates.

Gate 1: technical minimum

Requires:

  1. resolvable well identity
  2. usable depth track
  3. required curves
  4. no critical unit conflict

Gate 2: spatial minimum

Requires:

  1. source CRS resolved
  2. vertical datum acceptable
  3. transform chain documented

Gate 3: decision-grade minimum

Requires:

  1. completion context adequate
  2. depletion context adequate
  3. operability not clearly blocked
  4. evidence pack complete

JSON Output Contract

The ranked reopening-target output contract is defined in:

Output intent

This contract is designed for:

  1. portfolio summaries,
  2. UI worklists,
  3. downstream analytics,
  4. AI retrieval context.

Top-level fields

  1. event_type
  2. project_id
  3. scoring_profile_key
  4. scoring_version
  5. generated_at
  6. candidate_count
  7. summary
  8. candidates

Candidate-level fields

  1. target_id
  2. rank
  3. well_id
  4. source_candidate_id
  5. classification
  6. historic_payload_class
  7. remaining_payload_class
  8. depletion_risk
  9. operability_status
  10. data_confidence
  11. static_score
  12. dynamic_score
  13. operability_score
  14. confidence_score
  15. total_score
  16. blocking_reason
  17. recommended_action
  18. evidence_pack_id
  19. interval
  20. archie_assumptions
  21. score_inputs
  22. assumptions

Example output


{
  "event_type": "welllog.reopening_target_ranked",
  "project_id": "kern_reopen_demo",
  "scoring_profile_key": "earthbond_reopen_v1",
  "scoring_version": "earthbond.reopen.v1",
  "generated_at": "2026-03-23T17:00:00Z",
  "candidate_count": 2,
  "summary": {
    "class_counts": {
      "A": 1,
      "B": 1
    },
    "blocked_count": 0,
    "review_ready_count": 2
  },
  "candidates": [
    {
      "target_id": "9a7e...",
      "rank": 1,
      "well_id": "0423000123",
      "source_candidate_id": "dc91...",
      "classification": "A",
      "historic_payload_class": "strong_bypassed_pay",
      "remaining_payload_class": "high_remaining_potential",
      "depletion_risk": "moderate",
      "operability_status": "workover_feasible",
      "data_confidence": "high",
      "static_score": 0.82,
      "dynamic_score": 0.73,
      "operability_score": 0.68,
      "confidence_score": 0.88,
      "total_score": 0.77,
      "blocking_reason": null,
      "recommended_action": "Prioritize cased-hole review and recompletion planning.",
      "evidence_pack_id": "a2c1...",
      "interval": {
        "event_no": 3,
        "top_tvdss_m": 2134.2,
        "base_tvdss_m": 2142.8,
        "gross_thickness_m": 8.6,
        "net_thickness_m": 6.9
      },
      "archie_assumptions": {
        "rw_value": 0.12,
        "rw_source": "offset_analog",
        "a_factor": 1.0,
        "m_exponent": 2.0,
        "n_exponent": 2.0,
        "sw_model": "archie",
        "sw_confidence": "medium"
      },
      "score_inputs": {
        "vsh": 0.21,
        "phie": 0.16,
        "rt": 18.4,
        "sw": 0.43,
        "water_cut_trend": "stable",
        "offset_drainage": "limited"
      },
      "assumptions": {
        "trajectory_mode": "minimum_curvature",
        "completion_context": "partial",
        "pressure_data": "missing"
      }
    }
  ]
}

Relationship To Existing Bypassed-Pay Contract

The older contract:

should remain the interval-discovery contract.

It is now hardened with:

  1. recommended_action
  2. completion_status
  3. position_confidence
  4. cone radius outputs,
  5. evidence_pack_id
  6. cutoffs_applied

Use the contracts like this:

  1. bypassed-pay contract = interval discovery output,
  2. reopening-target contract = portfolio decision output.

Worklist UI Design

The worklist should not be a raw table dump.

It should be a decision surface.

Page layout

flowchart TD A["Sticky Summary Header"] --> B["Left Filter Rail"] A --> C["Main Ranked Target Table"] C --> D["Detail Drawer"] D --> E["Evidence / Gaps / Scores Tabs"] D --> F["Map / 3D Context Panel"]

Sticky summary header

Always visible while scrolling.

Contains:

  1. total targets
  2. count by class A/B/C/D/Q
  3. blocked count
  4. review-ready count
  5. active scoring profile
  6. last generated timestamp

Left filter rail

Filters should be explicit and domain-aware.

Required filters:

  1. project
  2. field / reservoir
  3. classification
  4. minimum total score
  5. maximum depletion risk
  6. operability status
  7. data confidence
  8. evidence completeness
  9. only wells with no critical spatial gaps
  10. only targets with recommended action available

Main ranked target table

One row per reopening target.

Columns:

  1. rank
  2. well id / well name
  3. class
  4. total score
  5. static score
  6. dynamic score
  7. operability score
  8. confidence score
  9. remaining payload class
  10. depletion risk
  11. operability status
  12. recommended action
  13. evidence status

Detail drawer

Opens when a row is selected.

Tabs:

  1. Score Breakdown
  2. Interval
  3. Gaps
  4. Evidence
  5. Production / Depletion
  6. Spatial

Score Breakdown tab

Shows:

  1. four component bars
  2. weight profile
  3. formula version
  4. blocking reason if any
  5. assumptions

Interval tab

Shows:

  1. event number
  2. top/base depth
  3. top/base TVDSS
  4. net/gross
  5. Vsh
  6. PHIE
  7. Rt
  8. Sw and Archie assumptions

Gaps tab

Shows:

  1. structured gaps
  2. severity
  3. promotion action
  4. whether each gap blocks reopening or only blocks 3D/spatial publication

Evidence tab

Shows:

  1. evidence-pack link
  2. source files
  3. completion sources
  4. production sources
  5. transform provenance

Production / Depletion tab

Shows:

  1. cumulative production
  2. water cut trend
  3. offset drainage indicators
  4. injector proximity or sweep flags

Spatial tab

Shows:

  1. well location confidence
  2. CRS / vertical datum summary
  3. ECEF anchor status
  4. linked 2D/3D context panel

User Roles

viewer

Can:

  1. read ranked targets,
  2. filter,
  3. open details.

operator

Can:

  1. annotate,
  2. change review status,
  3. export selected target sets.

project_admin

Can:

  1. activate scoring profiles,
  2. rerun ranking,
  3. adjust project-scoped thresholds.

platform_admin

Can:

  1. modify canonical scoring profiles,
  2. change formula defaults,
  3. audit profile history.

Recommended Future API Endpoints

These are the natural next contracts to expose:

  1. POST /well-logs/jobs/reopen-rank
  2. GET /projects/{project_id}/portfolio/reopening-targets
  3. GET /projects/{project_id}/reopening-targets/{target_id}
  4. GET /projects/{project_id}/reopening-targets/export

Why This Design Is Safer

This design avoids a common mistake:

using one score to hide the reason a well is high or low priority.

By separating:

  1. static quality,
  2. remaining payload,
  3. operability,
  4. confidence,

the platform stays auditable and explainable.

That is mandatory if scientists and engineers are expected to trust the ranking.

Next Implementation Step

After this schema and contract layer, the next code work should be:

  1. add worker logic that writes ops.well_reopening_targets,
  2. expose portfolio read APIs,
  3. build the actual reopening worklist page against those APIs,
  4. add export and review-state actions.