feat(abi): repair from the recorded verdicts rather than an ad-hoc scan #206

Merged
pat-s merged 1 commit from feat/repair-from-recorded-verdicts into main 2026-09-07 18:46:51 +00:00
Owner

Why

The reprex found 44 routed-path failures: Rcpp, Matrix and RJSONIO served to R 4.4 from 4.5 builds. Two causes, both now fixed (#205 here, #129 in bincraft) — but the repair itself also needs redoing, and the lists it ran from no longer exist.

Those lists came from a one-off local symbol scan, seeded from a candidate set derived on a single slot. That made them a lower bound by construction: the scan found 846 package-slot pairs, while inspecting every object found 4077 unsafe.

abi_flat_safety now holds the authoritative answer for every slot, written by the flat-safety backfill from the binaries themselves:

95418 inspected, 91325 safe, 4077 unsafe (4.3%)

against the 93% of compiled packages the source classifier suspects.

What it does

  • local/list-unsafe-flat-objects.R prints the objects recorded as unable to load under some minor, for one slot.
  • The workflow rebuilds each under every R minor installed in the image, with no --sensitive-only gate. Since bincraft v5.3.0 the destination is decided by the built binary's symbols, so a package needing a per-minor slot lands there and a portable one lands in the flat slot. Gating on the source classifier is exactly what let Rcpp slip through.

Safety

It fails loudly when a slot has no verdicts at all, rather than printing an empty list. An empty repair list is indistinguishable from "nothing to repair" and would read as success while doing nothing — the same shape of silent failure as the missing PGPASS.

crow lint passes.

After this

Run it fleet-wide, re-index, then re-run the reprex. The routed paths are the ones that must come back clean; the flat form's failures are the separate prune question.

## Why The reprex found 44 routed-path failures: `Rcpp`, `Matrix` and `RJSONIO` served to R 4.4 from 4.5 builds. Two causes, both now fixed (#205 here, #129 in bincraft) — but the repair itself also needs redoing, and the lists it ran from no longer exist. Those lists came from a one-off local symbol scan, seeded from a candidate set derived on a single slot. That made them a lower bound by construction: the scan found 846 package-slot pairs, while inspecting every object found **4077** unsafe. `abi_flat_safety` now holds the authoritative answer for every slot, written by the flat-safety backfill from the binaries themselves: ``` 95418 inspected, 91325 safe, 4077 unsafe (4.3%) ``` against the 93% of compiled packages the source classifier suspects. ## What it does - `local/list-unsafe-flat-objects.R` prints the objects recorded as unable to load under some minor, for one slot. - The workflow rebuilds each under **every** R minor installed in the image, with **no `--sensitive-only` gate**. Since bincraft v5.3.0 the destination is decided by the built binary's symbols, so a package needing a per-minor slot lands there and a portable one lands in the flat slot. Gating on the source classifier is exactly what let `Rcpp` slip through. ## Safety It **fails loudly when a slot has no verdicts at all**, rather than printing an empty list. An empty repair list is indistinguishable from "nothing to repair" and would read as success while doing nothing — the same shape of silent failure as the missing `PGPASS`. `crow lint` passes. ## After this Run it fleet-wide, re-index, then re-run the reprex. The routed paths are the ones that must come back clean; the `flat` form's failures are the separate prune question.
The earlier repair worked from package lists produced by a one-off local symbol
scan. Those lists were derived from a candidate set seeded on one slot, so they
were a lower bound by construction, and they do not survive the machine that
made them.

abi_flat_safety now holds the authoritative answer for every slot: the
flat-safety backfill inspected all 95418 objects and recorded which cannot load
under which minor. 4077 are unsafe, against the 93% of compiled packages the
source classifier suspects.

Each object is rebuilt under every installed R minor with no --sensitive-only
gate. Since bincraft v5.3.0 the destination is decided by the built binary's
symbols, so a package needing a per-minor slot lands there and a portable one
lands in the flat slot. Gating on the source classifier is what let Rcpp slip
through and break every R 4.4 client on the slot.

This change will:

- add local/list-unsafe-flat-objects.R, printing the recorded unsafe objects
- fail loudly when a slot has no verdicts at all, since an empty repair list
  would otherwise read as "nothing to do"
- add a manual workflow rebuilding them under every installed minor
pat-s merged commit ee4562d44c into main 2026-09-07 18:46:51 +00:00
pat-s deleted branch feat/repair-from-recorded-verdicts 2026-09-07 18:46:51 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
devxy/build-cran-binaries!206
No description provided.