Design: classify failing binary builds and auto-propose registry patches #115

Closed
opened 2026-07-14 13:54:36 +00:00 by pat-s · 0 comments
Owner

Summary

Turn recurring build failures into triaged patch suggestions instead of hand-scraping Crow logs.
The single_builds metadata table already records every failure with its error text, so we can classify those errors against known signatures and open PRs that pre-fill local/patches/registry.json entries, keeping the existing human review gate.

Motivation

Adding a patch today is fully manual: a build fails, someone reads the Crow log, recognises the failure class (musl + bundled native dep, a removed TBB header, a system-lib link leak, ...), picks the right fix tier, and hand-writes a registry.json entry.
The recent entries show the recurring shapes:

  • RcppParallel bundled Intel TBB fails on musl / g++ 15 (disable-tbb.patch).
  • fs links system libuv and ships a binary with NEEDED libuv.so.1 (force-vendored-libuv.patch).
  • rstan / StanHeaders includes the removed tbb/tbb_stddef.h (-DTBB_INTERFACE_NEW, #114).

These are a small, repeating set of fingerprints, which is exactly what a classifier is good at.

What already exists (foundation is in place)

  • bincraft::store_build_metadata() writes error_occurred and error_text (plus name, tag, platform, arch, r_version, timestamp) into the single_builds Postgres table (r-binaries.devxy.io:15432/build_metadata).
  • The patch registry, schema, validator (local/validate-patches.R), and the bincraft ingestion/isolated-build path are all live.
  • patchhash already auto-invalidates cached patched binaries when an entry or its diff changes, so a proposed entry can be trial-built in isolation without polluting the real cache.

So the missing piece is not capture; it is classification + proposal.

Proposed design (staged, cheapest first)

1. Failure view (query-only, no schema change)

A helper (e.g. local/failing-builds-report.R) that queries single_builds WHERE error_occurred and groups by a normalised error fingerprint, so we can see "N packages, M platforms, same root error" at a glance.
Normalisation strips version numbers, temp paths (/tmp/Rtmp...), and package-specific tokens from error_text so the same root cause collapses to one bucket.

2. Signature classifier (rules first, LLM for the long tail)

Map a normalised error_text to a suggested fix tier. Seed rules from the existing entries:

Error signature Suggested fix
tbb/tbb_stddef.h: No such file makevars CPPFLAGS += -DTBB_INTERFACE_NEW
NEEDED libuv.so.1 / dyn.load of *.so fails on missing runtime lib force-vendored / static-link source patch
USE_TBB ... is not supported / bundled TBB build hang on musl RcppParallel disable-tbb style override
unmatched flag for human triage, no auto-suggestion

Each rule carries a confidence and the tier (env / configure_args / makevars / patch).
Unknown signatures are surfaced for a human, never guessed at.

3. Propose, do not apply (human gate stays)

When a failing build matches a known signature and the package has no current registry entry, open a PR (or issue) with the pre-filled entry + reason, run the validator, and let an isolated trial build confirm before merge.
Acceptance criteria = validator passes + the trial patched build succeeds + the previously-failing dependent installs.

4. Feedback loop

Track proposed-vs-merged and signature hit rate so the rule set improves, and so a signature that stops matching (upstream fixed it) can retire its entry.

Explicit non-goals / guardrails

  • No autonomous merging of novel source diffs. Selecting a known env/makevars lever is safe to automate as a suggestion; generating a brand-new .patch that silences a compile error is exactly how we ship a broken-but-installable binary (the fs/libuv failure mode). That stays human-reviewed.
  • No change to the public src/contrib index.
  • No new failure-capture pipeline: reuse single_builds.error_text.

Suggested first step

Build 1 + 2 (failure view + rule-based classifier over single_builds) as a read-only reporting script.
That immediately replaces "user pastes a log" with a triaged suggestion, and is a safe place to validate the signature set before wiring up automated PR creation in step 3.

## Summary Turn recurring build failures into triaged patch suggestions instead of hand-scraping Crow logs. The `single_builds` metadata table already records every failure with its error text, so we can classify those errors against known signatures and open PRs that pre-fill `local/patches/registry.json` entries, keeping the existing human review gate. ## Motivation Adding a patch today is fully manual: a build fails, someone reads the Crow log, recognises the failure class (musl + bundled native dep, a removed TBB header, a system-lib link leak, ...), picks the right fix tier, and hand-writes a `registry.json` entry. The recent entries show the recurring shapes: - `RcppParallel` bundled Intel TBB fails on musl / g++ 15 (`disable-tbb.patch`). - `fs` links system libuv and ships a binary with `NEEDED libuv.so.1` (`force-vendored-libuv.patch`). - `rstan` / StanHeaders includes the removed `tbb/tbb_stddef.h` (`-DTBB_INTERFACE_NEW`, #114). These are a small, repeating set of fingerprints, which is exactly what a classifier is good at. ## What already exists (foundation is in place) - `bincraft::store_build_metadata()` writes `error_occurred` and `error_text` (plus `name`, `tag`, `platform`, `arch`, `r_version`, `timestamp`) into the `single_builds` Postgres table (`r-binaries.devxy.io:15432/build_metadata`). - The patch registry, schema, validator (`local/validate-patches.R`), and the bincraft ingestion/isolated-build path are all live. - `patchhash` already auto-invalidates cached patched binaries when an entry or its diff changes, so a proposed entry can be trial-built in isolation without polluting the real cache. So the missing piece is not capture; it is **classification + proposal**. ## Proposed design (staged, cheapest first) ### 1. Failure view (query-only, no schema change) A helper (e.g. `local/failing-builds-report.R`) that queries `single_builds WHERE error_occurred` and groups by a normalised error fingerprint, so we can see "N packages, M platforms, same root error" at a glance. Normalisation strips version numbers, temp paths (`/tmp/Rtmp...`), and package-specific tokens from `error_text` so the same root cause collapses to one bucket. ### 2. Signature classifier (rules first, LLM for the long tail) Map a normalised `error_text` to a suggested fix tier. Seed rules from the existing entries: | Error signature | Suggested fix | | --- | --- | | `tbb/tbb_stddef.h: No such file` | makevars `CPPFLAGS += -DTBB_INTERFACE_NEW` | | `NEEDED libuv.so.1` / dyn.load of `*.so` fails on missing runtime lib | force-vendored / static-link source patch | | `USE_TBB ... is not supported` / bundled TBB build hang on musl | RcppParallel `disable-tbb` style override | | unmatched | flag for human triage, no auto-suggestion | Each rule carries a confidence and the tier (`env` / `configure_args` / `makevars` / `patch`). Unknown signatures are surfaced for a human, never guessed at. ### 3. Propose, do not apply (human gate stays) When a failing build matches a known signature **and** the package has no current registry entry, open a PR (or issue) with the pre-filled entry + `reason`, run the validator, and let an isolated trial build confirm before merge. Acceptance criteria = validator passes + the trial patched build succeeds + the previously-failing dependent installs. ### 4. Feedback loop Track proposed-vs-merged and signature hit rate so the rule set improves, and so a signature that stops matching (upstream fixed it) can retire its entry. ## Explicit non-goals / guardrails - **No autonomous merging of novel source diffs.** Selecting a known env/makevars lever is safe to automate as a *suggestion*; generating a brand-new `.patch` that silences a compile error is exactly how we ship a broken-but-installable binary (the `fs`/libuv failure mode). That stays human-reviewed. - No change to the public `src/contrib` index. - No new failure-capture pipeline: reuse `single_builds.error_text`. ## Suggested first step Build **1 + 2** (failure view + rule-based classifier over `single_builds`) as a read-only reporting script. That immediately replaces "user pastes a log" with a triaged suggestion, and is a safe place to validate the signature set before wiring up automated PR creation in step 3.
pat-s closed this issue 2026-07-14 14:45:26 +00:00
Sign in to join this conversation.
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#115
No description provided.