AI-assisted data validation

Validating sanity configs with an AI agent: methodology notes

Context. CoRE Stack's data sanity framework (computing/sanity/) checks pipeline outputs against YAML rule configs: 34 configs, one per pipeline. Each config checks the pipeline's output in two forms, the vector layer and the stats Excel sheet. I did this work with Claude Code: first by hand on two pipelines, then by having agents repeat the method on all the others.

Approach:

  1. walk in working through adding validation for some pipelines
  2. ask claude to learn that process as a skill
  3. ask claude for more insights

1. Understanding the pipelines and output

Few things stood out:

Possible limitations:

  1. Schema: Is it readable and useful? Does the schema encourage good practices and discourage bad ones?
  2. Rules: Are the rules well-written? I noticed some rules that were either:
    1. not being matched with any field, or
    2. matching field in only one of excel/vector but targeting both, or
    3. (in cropping intensity) targeting hard-coded names for dynamically generated field names
  3. Functionality: Are the rule types good enough to find real bugs in production data? What are we missing that we should catch?

3. Have the agent repeat the method on every pipeline

I asked Claude to do what I had done by hand, for each pipeline:

I gave it the prod API key so it could fetch real data: two tehsils from different regions, Masalia (Jharkhand) and Raptadu (Andhra Pradesh).

The workflow became a reusable skill, because I wanted the lessons from the first two pipelines applied properly to the rest, not rediscovered each time. The skill lives in .claude/skills/sanity-config/:

Five parallel agents applied the skill to the other 33 configs, grouped by area. Each edited only its own configs and reported findings back.

Before After
Failing forms (config × tehsil × vector/Excel) 54 6, all real data problems
Rules that matched no field ~70, in 22 configs 0
Rules that don't catch a broken field never tested 0

That fixed avenue 2 (usage) and worked around most of avenue 1 (representation): vector and Excel rules are now separate, patterns replace hard-coded years, and presence checks are explicit.

4. Review each finding before sharing it

Findings went into TODO.md, which doubles as the PR description: prod data problems, bugs in the export code, framework gaps, and blind spots. I reviewed each item one at a time and rewrote it myself:

5. What found the bugs: rules or exploration?

Asking for provenance gave the most important result for avenue 3.

How it was found Findings
A rule written in advance, from the pipeline's physics Negative ET in Masalia (ET ≥ 0)
A rule that already existed Unnamed rivers (Excel river_name_not_null)
A rule written after the problem was seen in the data village_id 0 in two exports; null basin and watershed codes in a stale sheet
The skill's vector-vs-sheet id check (tooling, not a rule) Stale stats sheets in 9 config/tehsil pairs; restoration layer and sheet covering different MWS
Exploring the data Duplicate village polygons in Raptadu; LULC areas adding to 83% in Masalia; shrub area equal to forest area in every row; SOGE −9999 in whole columns
Reading the code Export bugs: NREGA category spelling, restoration field names, aquifer relabelling

The duplicate villages example.

What this tells us:

6. Takeaway

The agent was very productive:

But every finding needed review. The scripts made the rules testable, and checking each finding's provenance kept us honest about what the rules can actually find.

Next steps, in order of value:

  1. Add uniqueness and cross-field rule types.
  2. Make not_null treat "" as missing.
  3. Add a "≥ 0 or no-data" bound.
  4. Move the vector-vs-sheet id check into the framework.
  5. Add checks on pipeline inputs such as the census files.
  6. Test more tehsils.