Skip to content

feat(transducer): add data_maturity to observations - #853

Merged
jirhiker merged 4 commits into
stagingfrom
feat/transducer-data-maturity
Aug 19, 2026
Merged

feat(transducer): add data_maturity to observations#853
jirhiker merged 4 commits into
stagingfrom
feat/transducer-data-maturity

Conversation

@jirhiker

Copy link
Copy Markdown
Member

Task 3.3. Migration b2c3d4e5f6a7.

release_status is one column whose lexicon lists public and provisional as
siblings, so a reading could not be both visible and marked unreviewed.
Those are orthogonal questions — who may see it, and how much it should be
trusted. This adds the second axis.

A lexicon term rather than an is_provisional boolean, per your call: review is
a progression, not a switch, and a boolean cannot express the middle.

Terms

provisional · in review · approved

provisional and approved are what USGS publishes against — "provisional data
subject to revision" is the standard caveat on unapproved records. in review
is the intermediate state from the Aquarius approval levels USGS uses for
continuous time series (Working / In Review / Approved).

I folded Aquarius' Working into provisional, because to a consumer the two
are indistinguishable — both mean "not approved, may change". Say the word if
you want the full three-level workflow instead; it is one term and a lexicon
entry.

Existing rows are left NULL

Backfilling 88,666 legacy observations to provisional would assert something
about NMA data nobody has checked — some may well be approved. NULL reads as
"not stated", which is true.

A wrinkle worth knowing

provisional and approved already existed as terms: lexicon_term.term
is globally unique and categories share terms through an association table, so
only in review is new.

That means approved is now shared between review_status and data_maturity.
They ask different questions — review_status on the block records that a
Bureau human reviewed it and carries a reviewer_id, while data_maturity
describes the reading's revision state — and shared vocabulary is how this
lexicon is designed. Flagging it because two columns reading approved could
look like duplication.

Verification

  • Migration up and down against a database with 88,666 observations
  • The column is a foreign key onto lexicon_term, so a typo is rejected by the
    database — tested with probational
  • A test asserts release_status = public and data_maturity = provisional
    on the same row, which is the whole point
  • The loader defaults to provisional and refreshes maturity on upsert, so a
    corrected reading arriving as approved does not keep the older value
  • DataMaturity enum built from core/lexicon.json like every other status
    enum; the migration seeds the database to match

Still open

services/ngwmn_helper.py filters Thing.release_status == "public" for NGWMN
publication. San Acacia data becoming public needs to be intended there too —
that check is not in this PR.

🤖 Generated with Claude Code

jirhiker and others added 4 commits August 19, 2026 09:13
release_status is one column whose lexicon lists public and provisional as
siblings, so a reading could not be both visible and marked unreviewed. Those
are orthogonal questions -- who may see it, and how much it should be trusted --
and this adds the second axis.

A lexicon term rather than an is_provisional boolean: review is a progression,
not a switch, and a boolean cannot express the middle.

Terms follow USGS usage. provisional and approved are what USGS publishes
against; in review is the intermediate state from the Aquarius approval levels
used for continuous time series. Aquarius' Working is folded into provisional,
since to a consumer the two are indistinguishable.

Existing rows are left NULL rather than defaulted. Backfilling 88,666 legacy
observations to provisional would assert something about NMA data nobody has
checked -- some may be approved. NULL reads as not stated, which is true.

provisional and approved already existed as terms, since lexicon_term.term is
globally unique and categories share terms by association, so only "in review"
is new. approved is therefore shared with review_status; the two ask different
questions, and shared vocabulary is how this lexicon is built.

The loader defaults to provisional and refreshes maturity on upsert, so a
corrected reading arriving as approved does not keep the older maturity.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
I left historical rows NULL on the grounds that nobody had established whether
legacy NMA data was approved. The evidence was in the same table:
nma_waterlevelscontinuous_pressure_qced records whether a reading was quality
controlled, which is the question data_maturity asks.

True becomes approved, false becomes provisional. All 88,666 rows in the
development database are qced, so they land as approved rather than as an
absence somebody would have to reconstruct later.

Rows where the flag is NULL stay NULL. Those did not come from the NMA
transducer tables, so there is no evidence either way, and NULL is honest where
a guess would not be.

The update runs after the foreign key is in place, so a bad value fails loudly
rather than persisting.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Coverage

79.47% total — gate is 75%.

Coverage for the Python files changed in this PR
Name Stmts Miss Cover Missing
automated_ingestion/ocotillo/loader.py 54 13 76% 60, 163-192
core/enums.py 58 0 100%
db/transducer.py 58 2 97% 98, 101
schemas/group.py 34 0 100%
schemas/transducer.py 24 0 100%
TOTAL 228 15 93%

@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Your pull request is automatically being deployed to Dagster Cloud.

Location Status Link Updated
ocotillo-automated-ingestion View in Cloud Aug 19, 2026 at 04:28 PM (UTC)

@jirhiker
jirhiker merged commit 09926b2 into staging Aug 19, 2026
3 checks passed
@jirhiker
jirhiker deleted the feat/transducer-data-maturity branch August 19, 2026 16:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant