Chapter 12

Build with Claude Code

You are not going to hand-write a variogram estimator. An agent will write it in ninety seconds, and it will look right. The scarce skill is no longer implementation — it is knowing which of the plausible-looking answers is wrong, and having built the harness that proves it.

What changed, and what did not

Used to be the hard partIs now the hard part
CodeImplementing kriging correctlyKnowing kriging variance ignores the data values — and checking that it does
DataParsing the drillhole tablesKnowing from/to are downhole, not vertical
ModellingWriting the CV loopKnowing a random CV loop is meaningless on autocorrelated data
OutputGetting a numberKnowing whether the number can be defended to a QP

Every item in the right-hand column is domain knowledge from Chapters 1–11. An agent will happily produce a confident, well-structured, beautifully documented implementation of the wrong thing, because the wrong thing is what the general-purpose literature does. Your job is to be the part of the loop that knows better.

The mental model

Treat the agent as an extremely fast, extremely well-read graduate who has never seen a drill core, has no idea this industry has legal language constraints, and will not tell you when it is guessing. That framing gets you to the right working style immediately: specify the domain constraints explicitly, and verify the domain claims independently.

Step 1 · Give the agent its guardrails

Before any project, put a CLAUDE.md at the repo root. This is context the agent reads on every turn, and it is where you encode the rules that keep it from doing the standard-but-wrong thing. Start from this:

# Exploration data analysis — working rules

## Domain rules (violating these is failing the task)

1. Drillhole `from`/`to` are DOWNHOLE depths, never vertical. Convert with
   minimum curvature before any 3-D work. Mining dip is negative from
   horizontal; inclination-from-vertical is `I = 90 + dip`.
2. Never average grades without length weighting (and density, for metal).
3. Never invent a threshold — cutoff grade, QA/QC limit, detection-limit
   substitution. Ask, or label it explicitly as an assumption in the output.
4. Below-detection values are CENSORED, not zero and not missing. State the
   substitution rule used.
5. Geochemistry is compositional. Log-ratio transform (CLR/ILR) before any
   multivariate method.
6. NEVER use random cross-validation on spatial data. Spatial block CV by
   default, with block size set from the variogram range.
7. Known deposits are POSITIVE-UNLABELED. Unlabeled != negative.
8. Product language: findings are "flagged" and "require review". Never
   "verified", "cleared", "certified", or "guaranteed".

## Engineering rules

- Every deterministic check ships with a known-answer test: a fixture with a
  planted error, asserting BOTH detection and non-detection.
- State assumptions in the output, not just in comments.
- Show me the plan before writing more than ~50 lines.
- If you are uncertain whether something is a domain convention, say so
  explicitly rather than picking one.
Why rule 3 matters more than the rest

An invented threshold is the most dangerous failure mode in this domain, because it is invisible. A cutoff grade silently defaulted to 0.5% produces a complete, plausible, professional-looking intercept table that is simply not the analysis anyone asked for. Nothing errors. Nothing looks wrong. Make the agent surface every parameter it had to choose.

Step 2 · The loop

  1. Specify the decision, not the code. "I need to know whether the smoothing error in this block model is material at a 0.4% cutoff" beats "write a kriging function."
  2. Ask for a plan first. Read it for domain errors before any code exists. This is the cheapest possible place to catch them.
  3. Let it build. This part is genuinely fast; do not micromanage it.
  4. Verify independently. Not "does it run" — does it get a known answer right?
  5. Interrogate. Ask it to argue against its own result. "What assumption, if wrong, would most change this number?" is the highest-yield prompt in this chapter.

Verification is the deliverable

In a domain where you cannot check the answer against reality for ten years, the test harness is the work product. The pattern that works: synthesise data with a known answer, corrupt it in a known way, assert the pipeline recovers the truth.

> Generate a synthetic drillhole dataset with a KNOWN ground-truth grade
> field (Gaussian random field, spherical variogram, range 80 m, nugget
> 0.15, sill 1.0). Sample it along 40 realistic drill traces.
>
> Then run my estimator on those samples and check it recovers the
> variogram parameters within tolerance. Fail loudly if it does not.
>
> Do NOT tune the estimator to pass. If it does not recover them, tell me
> and we will work out why.

That last line matters. Without it you will get an estimator quietly adjusted until the test passes, which is worse than having no test at all.

Use a second agent as an adversary

Spawn a reviewer with a specific, sceptical brief rather than asking "is this good?" A subagent prompted as a Qualified Person reviewing this for scientific defensibility, whose job is to find the reason it is wrong catches things the implementing agent will not — because the implementing agent is motivated to have finished. Worth the tokens on anything you intend to show someone.

Step 3 · Prompts that work

WeakStrong
"Build a prospectivity model on this data" "Build a prospectivity model. Treat this as positive-unlabeled — apply the Elkan–Noto correction and report calibrated probabilities. Use spatial block CV with block size from the residual variogram range. Report PR-AUC and capture-efficiency at 5% of area, not ROC-AUC. Tell me which features are discovery proxies rather than geology."
"Compute the intercepts" "Compute intercepts at a 0.4% Cu cutoff, minimum composite length 2 m, maximum internal dilution 5 m. Length-weight the grades. List every hole with no reportable intercept rather than omitting it. Label these parameters as reporting choices, not validation thresholds."
"Does this look right?" "What assumption in this analysis, if wrong, would change the answer most? How would I test it with the data I have?"
"Clean this dataset" "Profile this dataset for the failure modes in Chapter 6: unit switches at date boundaries, over-limit truncation, duplicated row blocks, method changes, and below-detection handling. Report what you find with row-level evidence; change nothing yet."

The projects

Six sprints, ascending. Each gives you a starter prompt, a definition of done that is a defensible claim rather than working code, and — most importantly — the domain error the agent will probably make. Finding that error unaided is the actual exercise.

P1 · Desurvey and render a drill programme — an afternoon

> Pull mineral drillhole data for one project area from SARIG. Implement
> minimum-curvature desurveying from scratch — no library. Produce 3-D
> coordinates for every assay sample and render the traces coloured by
> grade with pyvista.
>
> Include a unit test against a two-station trajectory I can verify by hand.

Done when you can state how far the deepest hole's toe sits from its straight-line projection, and your hand-checked unit test passes.

What the agent will probably get wrong

The dip convention. It will plug mining dip (−60°) straight into a formula expecting inclination-from-vertical (30°), producing a plausible but rotated or inverted hole. Nothing will error. Check one hole by hand.

P2 · Prove kriging is a Gaussian process — a few days

> On a 2-D slice of this geochemical data, do it twice: (a) fit an
> experimental variogram and krige with PyKrige; (b) fit a GP in GPyTorch
> with the equivalent kernel, hyperparameters by marginal likelihood.
>
> Force identical hyperparameters and show the prediction surfaces agree
> to numerical tolerance. Then let each choose its own and explain the
> difference.

Done when the two surfaces match under forced hyperparameters, and you can explain the divergence when they are free.

What the agent will probably get wrong

The nugget↔noise correspondence and the sill↔signal-variance parameterisation. Misalign them and the surfaces look similar but do not match — and it is tempting to call that "close enough." Exact correspondence is the whole point of the exercise.

P3 · Measure the smoothing error — a week · do this one

> Compute tonnage and average grade above cutoff two ways: (a) directly
> from the kriged block model, and (b) from 200 sequential Gaussian
> simulations, applying the cutoff to EACH realisation and averaging the
> results afterwards.
>
> Sweep the cutoff. Plot both curves and quantify the gap as a percentage
> of contained metal.

Done when you can show where the curves diverge, explain the sign from Jensen's inequality, and name the cutoff range where using kriging directly would materially mislead a mine planner.

What the agent will probably get wrong

Averaging the realisations first and then applying the cutoff — which reconstructs the smoothed model and makes the entire effect vanish. The order of operations is the experiment. If your two curves lie on top of each other, that is why.

P4 · Four honest prospectivity models — two to four weeks

> Using the USGS tri-national grids, build MVT prospectivity four ways:
>   1. naive — random negatives, random 5-fold CV, ROC-AUC
>   2. same model, spatial block CV (block size from the variogram range)
>   3. same, plus PU learning with the Elkan-Noto c correction
>   4. leave-one-country-out: train US + Canada, test Australia
>
> One comparison table: ROC-AUC, PR-AUC, precision@50, capture-efficiency
> at 5% of area, plus a calibration plot. Do not tune between rows.

Done when you can explain why row 1 looks best and is worth least — and quantify the drop.

What the agent will probably get wrong

It will treat the falling score as a bug and try to fix it — adding features, tuning, resampling — until the numbers look respectable again. The collapse is the result. Say up front that a lower honest number is the successful outcome.

P5 · Plant errors, then catch them — two weeks

> Build a synthetic assay database with known ground truth. Inject the
> Chapter 6 failure modes: a lab bias over one date range, contaminated
> blanks after high-grade samples, a ppm/% switch mid-database, over-limit
> truncation, and a duplicated block of rows.
>
> Write deterministic detectors with an answer key. Assert BOTH detection
> and zero false positives on a clean control copy.
>
> Then model the corrupted data and show me the phantom spatial grade
> trend the batch bias created.

Done when every planted error is caught, the clean copy raises nothing, and you can display a kilometre-scale grade anomaly that is entirely an artifact of the laboratory.

What the agent will probably get wrong

It will inject the batch bias at random rows rather than correlating it with a contiguous drilling campaign — which destroys the lesson, because random bias averages out and campaign-correlated bias becomes fake geology. Insist the corruption be spatially coherent through the date field.

P6 · A drill-planning agent — a quarter

> Read the Intelligent Prospector v1.0 paper and run sisl/MineralExploration.
> Then build a simplified version: 2-D synthetic ore body, particle-filter
> belief, MINE/ABANDON terminal actions, POMCPOW planner.
>
> Benchmark against (a) a fixed grid and (b) a greedy one-step VOI policy.
> Plot decision quality vs number of measurements for all three.

Done when you reproduce the qualitative v1.0 finding — sequential planning reaching grid-level knowledge in roughly half the measurements — and can describe the particle-degeneracy behaviour in the two-body case.

What the agent will probably get wrong

It will quietly implement greedy one-step lookahead and call it a POMDP solver, because that is far easier and superficially similar. If your "planner" and your greedy baseline perform identically, you have two greedy baselines. Make it show you the search tree depth.

Stretch, and genuinely open

Add a second geological hypothesis with different spatial continuity and implement a falsification test that fires when neither hypothesis explains the data — the v2.0 problem from Chapter 10. This is close to the research frontier; a solid result is publishable.


Toolkit

NeedUse
Rasters, vectors, CRSrasterio, geopandas, xarray, rioxarray, pyproj
Variograms & krigingscikit-gstat, gstools, PyKrige, verde
Gaussian processesGPyTorch, GPflow
Geostatistical simulationgstools, GeoStats.jl (most complete open implementation)
3-D geological modellingGemPy
Geophysical forward & inverseSimPEG
3-D visualisationpyvista; QGIS for 2-D
Hex grids (the Lawley data uses H3)h3
POMDP planningPOMDPs.jl + POMCPOW.jl, or pomdp-py

Data

DatasetWhat's in itLink
USGS prospectivity gridsCD and MVT Pb-Zn prospectivity GeoTIFFs — the Lawley et al. outputsdata.usgs.gov
Tri-national critical minerals gridsNational-scale geophysical, geologic and mineral resource grids — the feature stackdata.usgs.gov
NRCan Open File 8836Lawley et al. training datasets for sediment-hosted Zn-Pbpublications.gc.ca
SARIG (South Australia)3,000,000+ rock sample analyses with drillhole locations, depths and methods; CSV exportcatalog.sarig.sa.gov.au
sisl/MineralExplorationIntelligent Prospector v1.0 source (MIT)github.com/sisl
awesome-open-geoscienceCurated index of open geoscience data and toolsgithub.com

How to write any of these up

  1. Question — the decision this informs, in one sentence.
  2. Data and provenance — exact source, version, date pulled, what you excluded and why.
  3. Assumptions — stationarity, support, detection-limit handling, cutoff, class prior. Every one. Unstated assumptions are how these analyses go wrong.
  4. Method and validation scheme, including why that scheme is the honest one.
  5. Result with uncertainty. Never a point estimate alone.
  6. What would change the answer — which additional data would move it most.
One habit above all

When the agent hands you a number, ask: could I defend this to a geologist who has spent thirty years on this deposit and does not believe me? If the honest answer is no, you do not have a result — you have output. The gap between those two words is the entire job.

Sources for this chapter

  • Claude Code documentationCLAUDE.md project memory, subagents, plan mode, hooks. Read the memory and subagent pages properly; they are what make the workflow above reproducible rather than ad hoc.
  • Anthropic — Claude Code best practices. Specification, verification loops, and giving agents a way to check their own work.
  • Known-answer testing is borrowed from cryptography and numerical software: validate against a case whose answer is independently known. In this domain the planted-error fixture of P5 is the natural form, and it is how Aethermine Audit's own check suite is built.
  • Software Underground — the community behind most of the open Python geoscience stack, and the best place to ask a question that has no Stack Overflow answer.
  • Scientific sources for each project live in the relevant chapter's own source list; the full annotated bibliography is Chapter 13.
Dataset links were verified at time of writing; government portals occasionally reorganise URLs.