Skip to content

RQ-61-CICAP (#1062) increment 1: retarget ONE non-required job to the idle rust-cpu pool - #1101

Merged
avrabe merged 1 commit into
mainfrom
feat/cicap-inc1-1062
Aug 28, 2026
Merged

RQ-61-CICAP (#1062) increment 1: retarget ONE non-required job to the idle rust-cpu pool#1101
avrabe merged 1 commit into
mainfrom
feat/cicap-inc1-1062

Conversation

@avrabe

@avrabe avrabe commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Refs #1062, #242. One runs-on line.

Measured, not argued

Four PRs opened within ~30 minutes each reached exactly 3/9 required contexts within minutes and then stalled for hours. The three that completed were the same three every time — Format, Version Pin Sweep, Rivet Validation — and those are precisely the three already on self-hosted. The six that stalled are the six on ubuntu-latest.

Same commits, same moment, same queue. Not job cost (Format is not cheaper than Clippy) — entirely which pool the job asks for.

runs-on census:  56 ubuntu-latest · 4 rust-cpu · 2 light · 1 macos
org runners:     12 online, 4 busy (OTHER repos), 8 IDLE (7 rust-cpu, 1 light)

Why this job

synth-provenance-v1 reconciliation gate needs only dtolnay/rust-toolchain — no apt, no Nix, no cargo install, no network package fetch. That is the same shape as Rivet Validation, which already runs on rust-cpu successfully. This move tests scheduling, not toolchain.

Why not a required job first, even though the required six are what actually blocks

A required context naming a label no online runner satisfies does not fail — it never runs, and a non-running required check deadlocks every merge in the repo. A non-required job that fails is a red someone can read and revert; a required job that never starts is a repo that cannot merge its own revert.

One job per PR, each with its own green cycle, in the risk order posted to #1062:

next needs risk
Claim Check checkout + python only none — no toolchain at all
Clippy rust-toolchain + cache low
Kani cargo-install of the verifier medium — network + disk
Test / Z3 sudo apt-get only after apt is confirmed on the image
Bazel nix + setup-bazel last or never — an environmental failure there looks exactly like a real proof failure

The cost being paid, measured this wave

Queue latency converts directly into wasted CI cycles. Two PRs accumulated green against a base that moved underneath them (#1096 at 8/9, #1099 at 9/9) — GitHub re-runs checks when the branch moves, never when the base does. Both had to be rebased and re-run from scratch; #1096 twice.

ci.yml ubuntu-latest 50 → 49; all workflows 56 → 55. Nothing else changed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

… idle rust-cpu pool

The smallest possible first step, and deliberately a NON-REQUIRED job.

MEASURED, not argued. Four PRs opened within ~30 minutes each reached
EXACTLY 3/9 required contexts within minutes and then stalled for hours.
The three that completed were the same three every time — Format, Version
Pin Sweep, Rivet Validation — and those are precisely the three that run
SELF-HOSTED. The six that stalled are the six on `ubuntu-latest`. Same
commits, same moment, same queue; the split is not explained by job cost
(Format is not cheaper than Clippy) but entirely by which pool the job
asks for.

    runs-on census:  56 ubuntu-latest · 4 rust-cpu · 2 light · 1 macos
    org runners:     12 online, 4 busy (OTHER repos), 8 IDLE (7 rust-cpu, 1 light)

WHY THIS JOB. `synth-provenance-v1 reconciliation gate` needs only
`dtolnay/rust-toolchain` — no apt, no Nix, no `cargo install`, no network
package fetch. That is the same shape as `Rivet Validation`, which already
runs on `rust-cpu` successfully, so the pool is proven for cargo-shaped
work and this move tests scheduling rather than toolchain.

WHY NOT A REQUIRED JOB FIRST, even though the required six are what
actually blocks. A REQUIRED context naming a label no online runner
satisfies does not fail — it NEVER RUNS, and a non-running required check
deadlocks every merge in the repo. A non-required job that fails is a red
someone can read and revert; a required job that never starts is a repo
that cannot merge its own revert. One job per PR, each with its own full
green cycle, in the risk order posted to #1062:

    Claim Check ... checkout + python ONLY .... next, after this cycle
    Clippy ........ rust-toolchain + cache .... then
    Kani .......... cargo install ............. then
    Test / Z3 ..... sudo apt-get .............. only after apt is confirmed
    Bazel ......... nix + setup-bazel ......... last or never — an
                                                environmental failure there
                                                looks exactly like a real
                                                proof failure

THE COST BEING PAID, measured this wave: queue latency converts directly
into wasted CI cycles. Two PRs each accumulated green against a base that
moved underneath them (#1096 at 8/9, #1099 at 9/9) because GitHub re-runs
checks when the BRANCH moves, never when the BASE does. Both had to be
rebased and re-run from scratch; #1096 twice. The longer a PR waits, the
likelier its green describes a tree that no longer exists.

Change is one `runs-on` line: ci.yml ubuntu-latest 50 -> 49, all workflows
56 -> 55. Nothing else moved.

Refs #1062, refs #242.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
@codecov

codecov Bot commented Aug 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@avrabe

avrabe commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

The moved job ran on the intended pool and passed — and the timing complicates the thesis, so here it is in full.

job: synth-provenance-v1 reconciliation gate (#396)
runner_name:  pulseengine-ci-01-10          <- one of the idle rust-cpu boxes from the census
labels:       [self-hosted, linux, x64, rust-cpu]
runner_group: hetzner-private
conclusion:   success

Measured against main's ubuntu-latest run of the same job

where                    queue wait     exec     total
branch rust-cpu                 3s      67s       70s
main   ubuntu-latest            4s      37s       41s

The self-hosted runner is nearly 2× slower to execute, and the queue wait was effectively equal. On this single measurement the move made this job worse.

That is not an argument against the change, but it does correct what the change is for:

  • The queue wait was 4s on main because the queue happened to be empty at that moment. The stall I measured earlier — four PRs each frozen at exactly 3/9 for hours — happened under contention, when a wave of PRs put ~50 jobs against ubuntu-latest at once. This run does not test that scenario and should not be read as if it did.
  • The benefit is contention relief on the required path, not per-job speed. Moving a non-required job off ubuntu-latest costs that job ~30s and frees an ubuntu-latest slot for the six required jobs that actually block merges. That is the trade being made deliberately.

What this changes about the plan

It argues for moving less, not more. Since each move costs execution time, the right target is only what relieves contention on the required path — not a blanket retarget of all 44 non-required ubuntu-latest jobs. The next steps in #1062's ranked order stand, but each should be justified by contention relief and re-measured, and a move that neither relieves contention nor runs faster should be reverted rather than kept for tidiness.

I would rather record this now than let "increment 1 was green" become evidence for a conclusion the numbers do not support.

@avrabe
avrabe merged commit e763586 into main Aug 28, 2026
58 checks passed
@avrabe
avrabe deleted the feat/cicap-inc1-1062 branch August 28, 2026 01:21
avrabe added a commit that referenced this pull request Aug 28, 2026
…ithout it, and that is my own miss

`main` is failing its own status-evidence gate right now:

  FAIL R4 RQ-61-CICAP: delivery commit on main (RQ-61-CICAP (#1062)
  increment 1 / PR #1101) but status is `proposed` and `landed:` does not
  acknowledge it

I merged #1101 without acknowledging it. R4 is evaluated over first-parent
history, so an id-naming delivery commit reddens main the MOMENT it lands
— which is exactly why I had been putting lane status flips ON the branch
before merging. I did that for every lane's PR this wave and then skipped
it for my own.

RECORDED, NOT FLIPPED. `RQ-61-CICAP` is explicitly multi-increment and the
REQUIRED jobs — the ones that actually block merges — have not moved, so
`fields.landed` is the honest record: "the increment landed, the artifact
is not done". Flipping to `implemented` would claim an outcome that has
not happened; silence is what R4 correctly calls red.

The note on the artifact also carries what increment 1 MEASURED, because
it corrects the plan rather than confirming it:

    rust-cpu       queue 3s  exec 67s  total 70s
    ubuntu-latest  queue 4s  exec 37s  total 41s

The self-hosted runner is ~2x SLOWER to execute and the queue wait was
equal — the queue happened to be empty. The benefit is CONTENTION RELIEF
on the required path, not per-job speed. So the conclusion is MOVE LESS,
NOT MORE: each further move needs its own contention justification and
re-measurement, and one that neither relieves contention nor runs faster
should be reverted rather than kept for tidiness.

Gate after this commit: status-evidence 0 failures (73 artifacts / 18
release files / 21 done-when predicates / 5 archaeology checks, 0 skipped),
claim_check 52/52.

Refs #1062, refs #1101.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
avrabe added a commit that referenced this pull request Aug 28, 2026
…1103)

* plan(v0.61): scope #1102 and #1100 — 11 -> 13

RQ-61-DANGLE (#1102, gale). rv32 ships an UNLINKABLE object with EXIT 0
when a retained function calls a DECLINED INTERNAL function. Reproduced by
the coordinator on a minimal 10-line module rather than the reported
real-world driver: an internal `i32.load offset=1048588` declines, the
exported caller is compiled anyway, and the object carries an undefined
`synth_func_0` that `ld.lld` refuses.

  Why the existing guards miss it: #952 converts a declined REQUESTED
  EXPORT into a non-zero exit, and #1013 gave aarch64 a refusal for the
  same class. Both are keyed on EXPORTS. The declined function here is
  INTERNAL, so no export guard fires — yet an exported entry point
  relocates against it. The mechanism exists and is pointed one level too
  shallow, which is this release's recurring shape.

  Cross-backend, measured on a module every backend now declines (#1093):
  rv32 exit 0 with the dangling symbol, aarch64 exit 1 (the #1013 guard
  working), ARM exit 0 with the skip and NOT YET CHARACTERISED. The
  artifact records why ARM is open rather than guessing: its relocatable
  objects carry `.rel.text` with NO `.symtab` here, so the probe that
  answers the question for rv32 and aarch64 cannot answer it for ARM — and
  a HEALTHY ARM object has the same shape, so the absent symtab is
  PRE-EXISTING and is not evidence of the defect. I nearly recorded it as
  one; the healthy-vs-declined baseline is what stopped that.

RQ-61-MCDCFLOOR (#1100). The MC/DC gate's report-side absolute floors are
layout-coupled: adding the #1093 guard moved reconstruction on functions
it never touched (32/141/60 -> 27/132/56) while the instrument side proved
nothing was lost (175 -> 176 branches, exactly one population differing,
19/19 byte-identical signatures elsewhere). Second instance after #990,
handled the same way — a re-statement WITH evidence, zero slack. The
artifact's point is that a floor re-stated on every unrelated-code PR is a
number being maintained, not a property being asserted, and lists the
candidate shapes (delta against the same run's population, per-function
scoping, or retiring the absolutes in favour of the stable surface).

Verified before bumping, on the CI-pinned rivet 0.23.0: 484 -> 486 with
all 13 RQ-61-* ids visible. ARTIFACT_FLOOR bumped in the same commit.

Every open issue again has a release assignment.

Refs #1102, #1100, #242.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* plan(v0.61): record RQ-61-CICAP increment 1 as landed — main is RED without it, and that is my own miss

`main` is failing its own status-evidence gate right now:

  FAIL R4 RQ-61-CICAP: delivery commit on main (RQ-61-CICAP (#1062)
  increment 1 / PR #1101) but status is `proposed` and `landed:` does not
  acknowledge it

I merged #1101 without acknowledging it. R4 is evaluated over first-parent
history, so an id-naming delivery commit reddens main the MOMENT it lands
— which is exactly why I had been putting lane status flips ON the branch
before merging. I did that for every lane's PR this wave and then skipped
it for my own.

RECORDED, NOT FLIPPED. `RQ-61-CICAP` is explicitly multi-increment and the
REQUIRED jobs — the ones that actually block merges — have not moved, so
`fields.landed` is the honest record: "the increment landed, the artifact
is not done". Flipping to `implemented` would claim an outcome that has
not happened; silence is what R4 correctly calls red.

The note on the artifact also carries what increment 1 MEASURED, because
it corrects the plan rather than confirming it:

    rust-cpu       queue 3s  exec 67s  total 70s
    ubuntu-latest  queue 4s  exec 37s  total 41s

The self-hosted runner is ~2x SLOWER to execute and the queue wait was
equal — the queue happened to be empty. The benefit is CONTENTION RELIEF
on the required path, not per-job speed. So the conclusion is MOVE LESS,
NOT MORE: each further move needs its own contention justification and
re-measurement, and one that neither relieves contention nor runs faster
should be reverted rather than kept for tidiness.

Gate after this commit: status-evidence 0 failures (73 artifacts / 18
release files / 21 done-when predicates / 5 archaeology checks, 0 skipped),
claim_check 52/52.

Refs #1062, refs #1101.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant