Commit graph build-cran-binaries/local/failing-builds-classify.R
Author SHA1 Message Date
6c03f278ec feat(local): aggregate blocked-on-dependency reporting by dependency (#131)
Some checks failed
ci/crow/cron/process-updates/2 Pipeline failed
ci/crow/cron/process-updates/7 Pipeline was successful
ci/crow/cron/process-updates/8 Pipeline was successful
ci/crow/cron/process-updates/3 Pipeline was successful
ci/crow/cron/process-updates/4 Pipeline was successful
ci/crow/manual/weekly-patch-proposals Pipeline was successful
ci/crow/cron/process-updates/9 Pipeline was successful
ci/crow/cron/process-updates/10 Pipeline was successful
ci/crow/manual/trial-build-registry/7 Pipeline failed
ci/crow/manual/trial-build-registry/5 Pipeline failed
ci/crow/manual/trial-build-registry/3 Pipeline failed
ci/crow/manual/trial-build-registry/13 Pipeline failed
ci/crow/manual/trial-build-registry/1 Pipeline failed
ci/crow/manual/trial-build-registry/11 Pipeline failed
ci/crow/manual/trial-build-registry/4 Pipeline failed
ci/crow/manual/trial-build-registry/2 Pipeline failed
ci/crow/manual/trial-build-registry/6 Pipeline failed
ci/crow/manual/trial-build-registry/9 Pipeline failed
ci/crow/manual/trial-build-registry/17 Pipeline failed
ci/crow/manual/trial-build-registry/15 Pipeline failed
ci/crow/manual/trial-build-registry/10 Pipeline failed
ci/crow/manual/trial-build-registry/14 Pipeline failed
ci/crow/manual/trial-build-registry/16 Pipeline failed
ci/crow/manual/trial-build-registry/12 Pipeline failed
ci/crow/manual/trial-build-registry/8 Pipeline failed
ci/crow/manual/trial-build-registry/18 Pipeline failed
ci/crow/cron/process-updates/13 Pipeline was successful
ci/crow/cron/process-updates/14 Pipeline was successful
ci/crow/cron/process-updates/15 Pipeline was successful
ci/crow/cron/process-updates/16 Pipeline was successful
## Why

With cascade detection (#128) live, the latest `auto-apply-patches` run did exactly the right thing — **proposed nothing** (`No auto-proposable candidates`) because every failure is a dependency cascade, and it surfaced the ~30 root-cause dependencies to fix.

But the "Blocked on a dependency" list printed **one line per fingerprint group**, so the same dependency repeated (rstan ×4, lpsymphony ×4, salso ×2, BH ×2, GO.db ×2, RcppCWB ×2, …), burying the priority.

## What

Aggregate blocked packages across all groups **by the dependency they wait on**:

- Expose `blocked_map` (package → dependency) from `build_triage_report()`.
- Add `blocked_by_dependency()` — dedupes dependents (a package in two groups counts once) and ranks dependencies by how many distinct dependents they block.
- Proposer and tracker (log + issue) now print one line per dependency, sorted by impact. Replaces the per-group `blocked_summary`.

## Result (same data, aggregated)

```
Blocked on a dependency (3 dependencies block 6 dependents; fix the dependency, not each dependent):
  RcppParallel             3 dependent(s)
  rstan                    2 dependent(s)
  sf                       1 dependent(s)
```

So the real run becomes a crisp, ranked worklist: RcppParallel (894), sf (128), rstan (~96), Rfast (33), clarabel/DescTools (26), Rglpk (22), xgboost (18), …

## Verified

New test covers cross-group aggregation, dedup (a dependent in two groups counted once), the example cap, and ranking. 112 tests pass; hooks pass.

Reviewed-on: #131
2026-07-16 21:24:03 +00:00
f9d399fac0 feat(local): detect dependency-cascade failures generally, not just RcppParallel (#128)
## Why (from the #127 trial-build gate)

The gate did its job: 0/3 passed, merge blocked. The log showed *why* -- BFpack, BayesERtools, GMLTM all fail while building their shared dependency **`rstan`**, not in their own code:

```
Failed to build source package rstan.
  .../StanHeaders/include/stan/math/prim/core/init_threadpool_tbb.hpp:9:10:
  fatal error: tbb/tbb_stddef.h: No such file or directory
```

So the per-package `-DTBB_INTERFACE_NEW` makevars entries the classifier proposed are useless for these packages -- they're blocked on `rstan` (which already has a registry entry). This is the **same dependency cascade** the RcppParallel `applies_to` guard catches, but `tbb-stddef-removed` is a generic signature with no such pin, so ~73 Stan packages kept getting proposed.

## What

Generalise cascade detection beyond the RcppParallel special case:

- `failing_dependency(error_text, package)` -- when the log names a **different** package as the one that failed to compile (`Failed to build source package X`, `compilation failed for package 'X'`, `dependency 'X' ... not available`), that package is the real cause.
- `build_triage_report()` now blocks any package whose **every** failing build is such a cascade: reported as `blocked_on` that dependency, never proposed a bogus per-package entry. A package that fails in its **own** compilation is still proposed.
- The `applies_to` (RcppParallel) and data-driven (rstan) cases are unified into one `blocked_packages` / `blocked_on` model; the report, proposer, and `blocked_summary` count the actually-blocked packages, and the blocked note shows even when a group also has genuine proposals.

## Effect

Next auto-apply run will stop proposing the rstan-blocked Stan packages (and any future dependency cascade) and surface them as "blocked on rstan" instead. Fixing `rstan` once clears the whole cluster.

## Verification

- New tests: `failing_dependency` (cascade vs own-compile vs none), and an end-to-end split where BFpack/GMLTM (blocked on rstan) are not proposed while an own-compile package still is.
- Full suite: 112 tests pass; all pre-commit hooks pass.

Refs #120, #127. (Separate follow-ups: fixing rstan's build itself, and quieting the gate's metadata-DB retry storm -- both root-caused to bincraft.)

Reviewed-on: #128
2026-07-16 08:23:54 +00:00
9bc4973159 fix(local): stop proposing per-dependent patches for dependency-cascade failures (#121)
All checks were successful
ci/crow/manual/weekly-patch-proposals Pipeline was successful
ci/crow/cron/process-updates/5 Pipeline was successful
ci/crow/cron/process-updates/17 Pipeline was successful
ci/crow/cron/process-updates/1 Pipeline was successful
ci/crow/cron/process-updates/6 Pipeline was successful
ci/crow/cron/process-updates/7 Pipeline was successful
ci/crow/cron/process-updates/2 Pipeline was successful
ci/crow/cron/process-updates/8 Pipeline was successful
ci/crow/cron/process-updates/9 Pipeline was successful
ci/crow/cron/process-updates/3 Pipeline was successful
ci/crow/cron/process-updates/12 Pipeline was successful
## Problem

The scheduled `--open-issue` run (issue #120) posted **800+** proposed entries, all `rcppparallel-bundled-tbb` on `ubuntu-2604`, each pre-filling `RcppParallel/disable-tbb.patch` for an unrelated package (`ACEsimFit`, `AovBay`, `AdaptGauss`, ...).

Root cause: those packages fail on ubuntu-2604 only because their **RcppParallel dependency** does not build there. bincraft records RcppParallel's TBB error text against each dependent, so every one of them matches the `rcppparallel-bundled-tbb` signature. Proposing a RcppParallel source patch for `ACEsimFit` is not just noise -- it is **broken**: the diff targets RcppParallel's `Makevars.in`, so it cannot apply to a dependent's source.

## Fix

Add an optional `applies_to` field that pins a package-specific fix to the package it targets:

- A signature whose fix is a curated per-package source patch (`rcppparallel-bundled-tbb` -> `RcppParallel`) is only ever proposed **for that package**.
- Other packages matching the signature are downstream failures, reported as **"blocked on `<dependency>`"** and never proposed a bogus entry. Fix the dependency once and the whole cascade clears.

Generic levers (the `tbb-stddef-removed` makevars fix) are unaffected -- they carry no `applies_to`, so they still apply to any matching package.

## Changes

- gate proposal generation in `build_triage_report()` on `applies_to`; add a `blocked_on` field to group records
- surface blocked groups in both `failing-builds-report.R` and `propose-patches.R` instead of the misleading "already registered" note
- document `applies_to` in the signature-table header

## Verification

- New tests: RcppParallel dependents are blocked (no `proposed_entries`, `blocked_on = "RcppParallel"`), while RcppParallel *itself* is still proposed when it is the failing package.
- Reproduced the avalanche end-to-end with a stubbed DB: 5 dependents now report "Blocked on RcppParallel: 5 package(s) fail because RcppParallel does not build" and **zero** candidates are emitted; a genuine `tbb-stddef` proposal in the same run is unaffected.
- Full suite: 84 tests pass; all pre-commit hooks pass.

Refs #120.

Note: the underlying build problem (RcppParallel failing on ubuntu-2604 despite its registry entry) is real and separate -- this PR stops the classifier from spamming broken per-dependent proposals about it.
Reviewed-on: #121
2026-07-14 18:40:41 +00:00
1c297c01bf feat(local): auto-propose registry patches and track the feedback loop (#117)
Implements steps 3 + 4 of #115, building on the classifier merged in #116. Now that bincraft **v4.4.3** applies registry `patch`/`makevars`/`configure_args` to the *target* package build (previously deps-only), a trial patched build is a meaningful acceptance gate, so the "propose" half is viable.

## Step 3 — propose, do not apply

- **`local/propose-patches.R`** — for each classified, safe fix affecting a package with no current registry entry, emits a pre-filled `registry.json` entry and validates the candidate set against a *temporary* merged registry (the real one is never touched unless asked).
  - default: print candidates + validation, **take no action**
  - `--write`: append entries to `registry.json` + the proposals ledger (you commit + open the PR)
  - `--open-issue`: post/update a Forgejo tracking issue (reuses the weekly-audit `httr2` + `FORGEJO_TOKEN` pattern)
- **`local/trial-build-patch.R`** — isolated bincraft build of one package with the registry applied (no upload/archive/metadata; `patchhash` keeps it out of the real cache). Exit 0/1, so it gates a CI step or manual pre-merge check.

The human gate stays: nothing merges. Acceptance = `validate-patches.R` passes (checked automatically) **and** the trial build succeeds. Novel source diffs and unknown signatures are never proposed (they carry `auto = FALSE`).

## Step 4 — feedback loop

- **`local/proposal-tracking.R`** (read-only) — signature hit rate (builds/pkgs/addressed/open per signature), proposed-vs-merged (a proposal counts merged once its package is in the registry), and retirement candidates (registry entries whose package no longer fails, i.e. likely fixed upstream).
- **`local/proposal-tracking-lib.R`** — the pure metric/ledger helpers.

## Supporting changes

- Refactored the classify helpers to expose a pure `build_triage_report()` + a list-returning entry builder; `failing-builds-report.R` now renders from the shared function (no behaviour change).
- `validate-patches.R` gains optional `PATCH_DIR`/`REGISTRY_FILE` overrides (backward-compatible) so a candidate registry can be validated in isolation.
- Documented the propose/trial-build/tracking workflow in `local/patches/README.md`.

## Verification

- 71 unit tests pass (incl. new `test-proposal-tracking-lib.R`) under the Dockerized R 4.5.3 build env.
- All pre-commit hooks pass (`air-format`, `validate-patches`, prettier, etc.).
- Smoke-tested all three entrypoints end-to-end with a stubbed DB: dry-run, `--write` (produces a registry that passes the canonical validator + a valid ledger, then reverted), and the tracker.

Closes #115

Reviewed-on: #117
2026-07-14 15:03:24 +00:00
f11ba7172f feat(local): classify failing binary builds and pre-fill registry suggestions (#116)
All checks were successful
ci/crow/cron/process-updates/9 Pipeline was successful
Implements steps 1 + 2 of #115: turn recorded build failures into triaged patch suggestions instead of hand-scraping Crow logs.

## What this adds

A **read-only** reporting pipeline over the `single_builds` metadata table. It never writes to the DB or the registry.

- `local/failing-builds-classify.R` — pure, DB-free helpers:
  - `normalise_error()` strips temp paths, version numbers, hex addresses, and the package name so the same root cause collapses to one fingerprint.
  - `fingerprint_error()` extracts the salient error line and normalises it.
  - `classify_error()` matches against a seed signature set; unmatched errors are never guessed at.
  - `propose_registry_entry()` renders a schema-valid `registry.json` entry.
- `local/failing-builds-report.R` — entrypoint: queries `single_builds WHERE error_occurred = TRUE AND removed = FALSE`, groups by root cause (signature when classified, fingerprint otherwise), classifies each group, and prints a triaged report. Flags: `--platform`, `--arch`, `--min`, `--json`; `PLATFORM`/`ARCH` env fallbacks.
- `local/tests/test-failing-builds-classify.R` — unit tests for the helpers.
- `local/patches/README.md` — documents the workflow.

## Seed signatures

Each rule carries a fix tier, confidence, and an auto/human-only flag:

| Signature | Fix | Disposition |
| --- | --- | --- |
| `tbb/tbb_stddef.h: No such file` | makevars `-DTBB_INTERFACE_NEW` | auto-proposable |
| RcppParallel bundled TBB (musl / new g++) | curated `disable-tbb.patch` | auto-proposable |
| system `libuv.so` link leak | force vendored/static lib | **human triage** (novel source diff) |
| unmatched | none | **human triage** |

## Guardrails honored

- No autonomous novel source diffs: only known env/makevars levers and already-curated package patches are auto-proposable; anything needing a brand-new diff, and any unknown signature, is routed to human triage.
- No DB or registry writes; no change to the public `src/contrib` index.
- Reuses `single_builds.error_text`; no new failure-capture pipeline.

## Verification

- All helper unit tests pass under the Dockerized R 4.5.3 build env.
- Pre-commit hooks pass (`air-format`, `validate-patches`, prettier, etc.).
- Smoke-tested the full report path with a stubbed DB; generated proposals pass the real `local/validate-patches.R`.

Steps 3 (auto-open PRs) and 4 (feedback loop) are intentionally deferred, per the issue's suggestion to validate the signature set first.

Closes #115

Reviewed-on: #116
2026-07-14 14:45:25 +00:00