Milestone 3 of 8

Classify valid, missing, and rejected rows

Apply the fixed first-failure order and give every source row one status with preserved evidence.

The parser now preserves every source row. This milestone gives each row one clear status without hiding the reason for an exclusion.

Milestone goal

Classify parsed rows as valid, missing, or rejected under one fixed first-failure order. Preserve the raw fields and source line in every result.

Classification interface

Implement a function such as:

Each returned record must retain:

source_line, record_id, sensor, observation, reading_raw, unit,
status, reason, reason_detail

For a valid row, also include a finite numeric reading value. For a missing or rejected row, keep reading_raw and leave the parsed reading absent or None; do not invent a replacement.

Apply the rules in order

Use this order for each parsed row:

  1. Row and column structure. A structurally incomplete record is rejected as malformed_row.
  2. Record identity. An empty ID is empty_record_id. A repeated ID is duplicate_record_id when it is not the first occurrence. The first occurrence continues through the remaining rules.
  3. Sensor. Any value other than north or south is unknown_sensor.
  4. Observation. The value must parse as an integer in 0..19; otherwise use invalid_observation.
  5. Unit. The value must be exactly deg_c; otherwise use unit_mismatch.
  6. Reading. A blank value is missing_reading. A non-numeric, non-finite, or out-of-range value is rejected as invalid_reading or reading_out_of_range, as appropriate.

The first failed rule wins. A blank reading becomes missing only when all earlier rules pass. A row with an unknown sensor and blank reading is rejected, not missing.

Every non-valid record must carry a stable machine-readable reason and a short reason_detail that names the failed rule. Use the same reason name for the same failure across fixtures.

Deliverables

Produce:

  • the classifier in src/pipeline.py or a small module it imports;
  • a classified record collection that still contains every source row;
  • one table in the report showing at least one valid, one missing, and one rejected row with source line and reason;
  • the stable reason vocabulary used by the implementation.

Checks

Use the public fixture and boundary cases to verify:

  • every input row produces exactly one classified record;
  • the first duplicate is allowed to continue and a later duplicate is rejected;
  • a blank reading is missing only after earlier fields pass;
  • an invalid numeric value and an out-of-range value retain different reasons;
  • an unknown sensor and a unit mismatch are not silently corrected;
  • when two rules fail, the earlier rule is the saved reason;
  • source lines, raw fields, and IDs remain unchanged.

The checks can verify status and reason strings. They cannot prove that a reader understands why the first-failure order matters, so explain one multi-defect example in your report.

Review

Read the classified public fixture from top to bottom. Ask whether a reader could reconstruct the decision for each excluded row from source_line, raw fields, status, and reason_detail. If not, the record does not yet carry enough evidence.

Next step

The next milestone writes three durable CSV partitions. It must serialize the classification without changing statuses, raw fields, IDs, or source lines.

HintFirst failure is a policy
The order is part of the contract. Do not let whichever conversion raises first decide the public reason by accident.
HintMissing is not invalid
A blank reading can be a useful status when the row's identity and other fields are sound. Keep it distinct from a value that cannot be parsed or trusted.

How to check your work

The supplied fixture includes a compact reason vocabulary and a deterministic first-failure implementation. Compare the public rows and boundary cases after your own classifier has produced evidence.

LLM PrimerClassify valid, missing, and rejected rowshttps://llmprimer.com/python/projects/inspect-and-validate-a-dataset/classify-valid-missing-and-rejected-rows© 2026 LLM Primer