# Embrapa FEBR (SiBCS) v0.9.29 benchmark — 2026-05-03

A/B at Order + Subordem level on the FEBR `febr-superconjunto.txt`
sample (n=554), comparing v0.9.27 to v0.9.29.

## Results

| Level    | v0.9.27 | v0.9.29 | Delta |
|----------|---:|---:|---:|
| Order    | 56.68 % (CI 52.7-60.6) | 56.68 % (CI 52.7-60.6) | 0.00 pp |
| **Subordem** | 9.93 % (CI 7.4-12.5) | **38.63 %** (CI 35.0-42.8) | **+28.70 pp** |

## Cumulative SiBCS Subordem trajectory

| Release | Subordem | Cumulative gain since v0.9.22 |
|---------|---:|---:|
| v0.9.22 | -- (not measured) | -- |
| v0.9.27 | 9.93 % | (initial measurement) |
| **v0.9.29** | **38.63 %** | **+28.70 pp** |

## Root cause analysis (the 190-Litolicos bug)

The v0.9.27 confusion analysis identified the dominant single-source
SiBCS Subordem error: 190 of the 191 FEBR Neossolos Litolicos were
being routed to "Neossolos Regoliticos" (the catch-all subordem in
the SiBCS Cap 12 key).

Diagnostic data on the 191 FEBR Litolicos:

| Property | Value |
|----------|-------|
| Number of horizons (median) | 1 |
| Max profile depth (median)  | 17.5 cm |
| Profiles with R / Cr / Rk designation | 1 / 191 (0.5 %) |
| Profiles with depth <= 50 cm | 191 / 191 (100 %) |
| Currently classified as Litolico (v0.9.27) | 1 / 191 (0.5 %) |

SiBCS Cap 12 (p 219) defines Neossolos Litolicos by lithic contact
within 50 cm. In the FEBR / BDsolos snapshot, surveyors document
this implicitly by stopping the profile description at the rock
boundary (median depth 17.5 cm) rather than entering a pseudo-R
horizon. The pre-v0.9.29 `neossolo_litolico()` test required
`contato_litico()` to return TRUE, which itself requires an
explicit `^R$|^Cr|^Rk` designation that FEBR almost never carries.

## Fix (v0.9.29)

`neossolo_litolico()` now adds an "implicit lithic contact" path:

- max profile depth <= 50 cm
- no B-horizon designation
- a non-empty bottom_cm column

Direct evidence (explicit R / Cr / Rk designation within 50 cm) is
preserved as the canonical path. Both paths are tested independently
in `tests/testthat/test-v0929-neossolo-litolico-heuristic.R`.

## Per-Subordem confusion before and after

Top mismatch token-pairs (ref Subordem -> pred Subordem) at v0.9.27:

| Ref -> Pred | Count |
|-------------|------:|
| neossolos litolicos -> neossolos regoliticos | 190 |
| argissolos amarelos -> argissolos vermelho-amarelos | 19 |
| argissolos vermelhos -> argissolos vermelho-amarelos | 13 |
| latossolos amarelos -> latossolos vermelho-amarelos | 12 |
| neossolos fluvicos -> neossolos regoliticos | 11 |
| neossolos quartzarenicos -> neossolos regoliticos | 9 |
| argissolos bruno-acinzentados -> argissolos vermelho-amarelos | 4 |

The v0.9.29 fix targets the first row (190 cases). The remaining
~50 Argissolo / Latossolo color confusions (Vermelho/Amarelo split
under FEBR-NA Munsell hue) are deferred to a future release as a
separate fix.

## Reproducibility

```r
library(soilKey)
peds <- load_febr_pedons(
  path = "<path>/embrapa_bdsolos/febr-superconjunto.txt",
  verbose = FALSE)

keep <- vapply(peds, function(p) {
  hz <- p$horizons
  !is.null(hz) && nrow(hz) > 0 && any(!is.na(hz$clay_pct))
}, logical(1))
peds <- peds[keep]

for (lvl in c("order", "subordem")) {
  res <- benchmark_run_classification(peds, system = "sibcs",
                                         level = lvl, boot_n = 500L)
  cat(sprintf("SiBCS %-10s n=%d  top1=%.4f  CI=[%.3f, %.3f]\n",
                lvl, res$n_evaluated, res$accuracy_top1,
                res$accuracy_ci[1], res$accuracy_ci[2]))
}
```
