cv2(provenance): land Cb.getCaptureStats on main + publish the guest release record #43

Merged
triform-admin merged 4 commits from agent/a4-guest-provenance into main 2026-07-29 11:08:24 +00:00

What

Reconciles the load-bearing guest commit onto main, and makes this repo — the one that builds the guest image — publish what it shipped.

Three source files (T1 reconcile) + two new provenance artifacts (T2).

T1 — the reconcile

origin/main..78e5bb4138c3 (head of the unmerged capstats-plus-rearm) was 4 commits:

commit disposition
a71b0d0 feat(cv2-capture): Cb.getCaptureStats LANDED (cherry-picked)
f5dcb60 fix(cv2-capture): FrameSink self-heal across RVH swap DROPPED — already on main
151c078, 78e5bb4 merge commits, no content
build-job-x264-t7.yaml DROPPED — see below

a71b0d0 is load-bearing. The monorepo hard-depends on Cb.getCaptureStats at isolator/src/vmm/pool.rs:5535 as the golden-snapshot capture health-gate. Without it the guest answers -32601, pool.rs takes the "legacy blind hold" path — and then return Ok(()), silently disarming the gate. That is the failure mode where a wedged renderer gets frozen into a golden snapshot and poisons every cold-start restored from it.

Verified git grep -c getCaptureStats origin/main -- capture/0 hits (rc=1). After this PR: 4.

f5dcb60 drop is correct — verified, not assumed. Identical git patch-id --stable:

561b33610dbfc0d18868a916b7b633d6c570e8e7  f5dcb60   (branch)
561b33610dbfc0d18868a916b7b633d6c570e8e7  b3359fb   (main, #38)

Same hash ⇒ same diff. No delta to land.

The build-job YAML is dropped deliberately. The branch version is not a change forward — it is ff95e0d (#39, which re-pinned OUR_REPO_REFmain) seen from before it landed, because the branch predates it. Taking it would silently revert the pin back to cv2/idle-refresh-capturer. Main's current state is already the coherent one.

Result: this branch's guest source tree is byte-identical to the shipped tree:

git diff --stat HEAD 78e5bb4138c3 -- . ':(exclude)infra/k8s'   # empty

T2 — closing the provenance loop

The monorepo's chromeless-auto-bump.sh resolves its target from BrowserSessionPool/sw-pool, declaring that pool "the source of truth — we follow, never lead". But sw-pool's template image is only ever hand-edited to match the monorepo pin. So CURRENT == TARGET by construction and the cron reports "up to date", exit 0, forever. This repo was not an input at any point. That is not a check that broke; it is a check that structurally cannot fail, because nothing in the loop can disagree with anything else.

build/guest-release.json gives the producer a voice so the comparison can come out false. Written by chromeless-kaniko-push.sh gated on Job Complete=True, so it can never claim an image that was not pushed.

Not in chromeless-build.sh: that runs inside the K8s Job, on a build node, as uid 1000, against a bootstrap clone with no credentials and no working tree. It cannot update a git-tracked file — wiring it there would be a mechanism that silently never runs.

Honest limitation: the script writes the file, it does not commit it — it prints the exact git commit command. An operator who pushes and never commits leaves the record stale, and the consumer-side check then fails on the mismatch. Stale-and-caught is the designed failure mode; silently-wrong is what is being removed.

Writer red-tested on all three arms (executed, not assumed):

  • real tag → full 40-char SHA + digest
  • cr7727-hotfixrefuses to write, file untouched
  • unknown SHA → records short SHA, warns, never fabricates

⚠️ The invariant is RED today — and that is the correct result

.commit (78e5bb4138c3…) is not an ancestor of main, and will not become one by this PR. A cherry-pick mints a new SHA. Source parity is not ancestry.

So an ancestry check fails today. That red is true: production is running a binary whose exact provenance is not on main. It is recorded in known_gap rather than hidden, and clears exactly one way — rebuild the guest from a main SHA and let the push step rewrite the file. Never by hand-editing the field.

Evidence — verified against the live artifact, not inferred

crane against the actually-shipping image:

created = 2026-07-10T08:06:42Z
digest  = sha256:34ff9751c814800086c488ede2d1e87a9be1d2570c5e94afcc5139c15b79a873

Extracted /usr/local/bin/chromeless (207MB) and ran the repo's own documented strings-gate:

CV2-CAPTURE-STATS   1     <- a71b0d0, ABSENT from main
CV2-CAPTURE-REARM   3
CV2-GPU-DEATH       2

The deployed guest really does carry the unmerged capstats work. This is direct proof of the drift, not an inference from the tag.

Scope

Source-only. No build is started — that is ~2.5–9h and operator-controlled under batch freeze.

tests/runtime/phase2-runtime-contract.shok.

## What Reconciles the load-bearing guest commit onto `main`, and makes this repo — the one that **builds** the guest image — publish what it shipped. Three source files (T1 reconcile) + two new provenance artifacts (T2). ## T1 — the reconcile `origin/main..78e5bb4138c3` (head of the unmerged `capstats-plus-rearm`) was 4 commits: | commit | disposition | |---|---| | `a71b0d0` `feat(cv2-capture): Cb.getCaptureStats` | **LANDED** (cherry-picked) | | `f5dcb60` `fix(cv2-capture): FrameSink self-heal across RVH swap` | **DROPPED** — already on main | | `151c078`, `78e5bb4` | merge commits, no content | | `build-job-x264-t7.yaml` | **DROPPED** — see below | `a71b0d0` is load-bearing. The monorepo hard-depends on `Cb.getCaptureStats` at `isolator/src/vmm/pool.rs:5535` as the golden-snapshot capture health-gate. Without it the guest answers `-32601`, `pool.rs` takes the "legacy blind hold" path — and then **`return Ok(())`**, silently disarming the gate. That is the failure mode where a wedged renderer gets frozen into a golden snapshot and poisons every cold-start restored from it. Verified `git grep -c getCaptureStats origin/main -- capture/` → **0 hits** (rc=1). After this PR: 4. **`f5dcb60` drop is correct — verified, not assumed.** Identical `git patch-id --stable`: ``` 561b33610dbfc0d18868a916b7b633d6c570e8e7 f5dcb60 (branch) 561b33610dbfc0d18868a916b7b633d6c570e8e7 b3359fb (main, #38) ``` Same hash ⇒ same diff. No delta to land. **The build-job YAML is dropped deliberately.** The branch version is not a change *forward* — it is `ff95e0d` (#39, which re-pinned `OUR_REPO_REF` → `main`) seen from *before* it landed, because the branch predates it. Taking it would silently revert the pin back to `cv2/idle-refresh-capturer`. Main's current state is already the coherent one. Result: this branch's guest **source tree is byte-identical to the shipped tree**: ``` git diff --stat HEAD 78e5bb4138c3 -- . ':(exclude)infra/k8s' # empty ``` ## T2 — closing the provenance loop The monorepo's `chromeless-auto-bump.sh` resolves its target from `BrowserSessionPool/sw-pool`, declaring that pool "the source of truth — we follow, never lead". But sw-pool's template image is only ever hand-edited to match the monorepo pin. So `CURRENT == TARGET` by construction and the cron reports "up to date", exit 0, forever. **This repo was not an input at any point.** That is not a check that broke; it is a check that structurally cannot fail, because nothing in the loop can disagree with anything else. `build/guest-release.json` gives the producer a voice so the comparison can come out false. Written by `chromeless-kaniko-push.sh` **gated on Job `Complete=True`**, so it can never claim an image that was not pushed. Not in `chromeless-build.sh`: that runs inside the K8s Job, on a build node, as uid 1000, against a bootstrap clone with no credentials and no working tree. It *cannot* update a git-tracked file — wiring it there would be a mechanism that silently never runs. **Honest limitation:** the script writes the file, it does **not** commit it — it prints the exact `git commit` command. An operator who pushes and never commits leaves the record stale, and the consumer-side check then fails on the mismatch. Stale-and-caught is the designed failure mode; silently-wrong is what is being removed. Writer red-tested on all three arms (executed, not assumed): - real tag → full 40-char SHA + digest - `cr7727-hotfix` → **refuses to write**, file untouched - unknown SHA → records short SHA, warns, never fabricates ## ⚠️ The invariant is RED today — and that is the correct result `.commit` (`78e5bb4138c3…`) is **not** an ancestor of `main`, and will not become one by this PR. A cherry-pick mints a new SHA. **Source parity is not ancestry.** So an ancestry check fails today. That red is true: production is running a binary whose exact provenance is not on `main`. It is recorded in `known_gap` rather than hidden, and clears exactly one way — rebuild the guest from a `main` SHA and let the push step rewrite the file. **Never by hand-editing the field.** ## Evidence — verified against the live artifact, not inferred `crane` against the actually-shipping image: ``` created = 2026-07-10T08:06:42Z digest = sha256:34ff9751c814800086c488ede2d1e87a9be1d2570c5e94afcc5139c15b79a873 ``` Extracted `/usr/local/bin/chromeless` (207MB) and ran the repo's own documented strings-gate: ``` CV2-CAPTURE-STATS 1 <- a71b0d0, ABSENT from main CV2-CAPTURE-REARM 3 CV2-GPU-DEATH 2 ``` The deployed guest really does carry the unmerged capstats work. This is direct proof of the drift, not an inference from the tag. ## Scope Source-only. **No build is started** — that is ~2.5–9h and operator-controlled under batch freeze. `tests/runtime/phase2-runtime-contract.sh` → `ok`.
Adds a read-only Cb.getCaptureStats method exposing the FrameSink
frame-production counter (frames_received_from_capturer) so the isolator
can verify a renderer is actually PRODUCING before freezing it into a
warm-snapshot golden.

ROOT CAUSE this enables fixing (poisoned warm-golden): the isolator's
golden-capture warmup starts FrameSink capture then blindly sleeps 3s and
assumes production. When the ~8% per-boot GPU wedge (run11: BeginFrame
ack-loop healthy but renderer produces ZERO frames) strikes during
capture, startFrameSinkCapture still SUCCEEDS (peer-independent pipe) so a
wedged, zero-producing renderer gets frozen into the golden. Every restore
is born-frozen; the poison persists on the per-worker hostPath cache. One
node (triform-6) took out ~25% of prod video this way.

The counter is the SAME frames_received the guest's cb_begin_frame_driver
uses to decide VERDICT=PRODUCING vs RENDERER-STARVED. Growing => healthy;
flat 0 => wedged (do not publish that golden).

Reuses the already-plumbed track_source_getter_ (lazy dispatch-time
resolve, CV2-69 order-safe); zero main_parts/content_browser_client
changes. Lock-free GetStats() copy, safe off-sequence. int32-saturated
CBOR (crdtp has no uint64 encoder; gate only reads 0-vs-growing).

Marker: CV2-CAPTURE-STATS (grep -a on the linked binary).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit a71b0d0943)
The producer side of the guest-image supply chain had no git-tracked
statement of what actually shipped. The monorepo's chromeless-auto-bump.sh
resolves its target from the k8s BrowserSessionPool/sw-pool object and
declares that pool "the source of truth — we follow, never lead"; sw-pool's
template image is only ever hand-edited to match the monorepo pin. So
CURRENT == TARGET always, and the bumper reports "up to date", exit 0,
forever. The chromeless repo is not an input at ANY point in that loop.
That is not a broken check — it is a green check that structurally cannot
fail, because nothing in it can ever disagree with anything else.

This file breaks the loop by giving the PRODUCER a voice: a git-tracked
record, in the repo that builds the artifact, of the exact commit and
digest that were pushed. A consumer-side check can then compare the
monorepo pin against this file and against main's history, and actually
be able to come out false.

Seeded by hand for the currently-shipping image because it predates the
writer; the next successful push overwrites it. Fields are flat and
literal so a checker needs no parsing cleverness:

  commit     full 40-char chromeless SHA the guest binary was built from
  image      fully-qualified ref, tag included (what a pin must equal)
  digest     sha256 manifest digest — the immutable identity; a tag can
             be moved, this cannot
  built_at   RFC3339 UTC

known_gap is the honest part. The shipping image was built from
capstats-plus-rearm, which was never merged, so `commit` is NOT an
ancestor of main and will not become one by cherry-picking (that mints a
new SHA). An ancestry check on this record is therefore EXPECTED to fail
today. That is the correct result, not a bug in the check: production is
running a binary whose exact provenance is not on main. It clears only by
rebuilding from main — never by hand-editing the field.

Verified against the live artifact rather than assumed: `crane config`
gives created=2026-07-10T08:06:42Z, and the repo's own documented
strings-gate against the extracted binary shows CV2-CAPTURE-STATS x1,
CV2-CAPTURE-REARM x3, CV2-GPU-DEATH x2 — i.e. the deployed guest really
does carry the unmerged capstats work.

Refs: build/README.md § provenance
Wires build/guest-release.json to the one step that knows an image really
exists in the registry: the kaniko push, gated on Job condition
Complete=True. The record therefore cannot claim an artifact that was
never pushed.

Why here and not in chromeless-build.sh (which stages the context and
writes context/IMAGE_TAG): that script runs INSIDE the K8s build Job, on
a build node, as uid 1000, against a bootstrap clone with no push
credentials and no working tree to commit into. It cannot update a
git-tracked file — so putting the writer there would be inventing a
mechanism that silently never runs. This script already executes on the
operator's workstation from a real checkout; it computes REPO_ROOT to
locate its own YAML template. The record is written where a human is
already standing in the repo that owns it.

Stated limitation, deliberately not papered over: this WRITES the file,
it does not commit or push it. The script prints the exact git command
and will not pretend otherwise. If an operator pushes an image and never
commits the diff, the record goes stale — and the consumer-side check
then fails on the disagreement between the monorepo pin and this file.
Stale-and-caught is the designed failure mode; silently-wrong is what we
are removing. Committing from a bare push script would mean a script that
mutates the operator's branch state as a side effect, which is worse.

The SHA is derived from the build TAG, never from the local checkout.
The operator's tree is routinely on some other branch — that is precisely
how the current drift arose — so a local `git rev-parse HEAD` would
confidently record a commit unrelated to the binary.

Three arms, each executed rather than assumed:
  - happy path      cr7727-78e5bb4138c3 -> full 40-char SHA + digest
  - non-commit tag  cr7727-hotfix       -> REFUSES to write, file untouched
  - unknown SHA     cr7727-deadbeefdead -> records short SHA, warns, never
                                           fabricates a full one

It also warns loudly when the recorded commit is not an ancestor of
origin/main — the exact condition that let an unmerged branch reach
production unnoticed. Digest resolution is best-effort (crane may be
absent); a missing digest degrades the record but never fails a good push.

Refs: build/guest-release.json
docs(cv2-build): document the guest-release provenance contract
Some checks failed
CI / Docs link check (pull_request) Failing after 1m33s
CodeQL / Analyze go (pull_request) Failing after 1m38s
CodeQL / Analyze javascript-typescript (pull_request) Failing after 1m38s
CI / Lint (pull_request) Failing after 2m25s
native-peer-gate / Build chromeless:ci for gate (pull_request) Failing after 2m36s
native-peer-gate / native-peer-gate-scaffold (permissive) (pull_request) Has been skipped
native-peer-gate / native-peer-gate-strict (M7 gate) (pull_request) Has been skipped
CI / Build container image (pull_request) Failing after 3m11s
CI / Container smoke test (pull_request) Has been skipped
E2E / docker-compose + Playwright (pull_request) Failing after 3m23s
909c132d39
Spells out the schema, the two invariants a consumer should assert
(monorepo pin == .image; .commit is an ancestor of main), and — most
importantly — why the ancestry invariant is EXPECTED to be red today, so
the next person to see that red does not "fix" it by editing the field.

Records the non-obvious bit explicitly: the reconcile cherry-pick makes
main's guest SOURCE byte-identical to the shipped tree, but a cherry-pick
mints a new SHA, so the recorded commit still is not an ancestor. Source
parity is not ancestry. Only a rebuild from main clears it.

Also documents the closed loop this replaces (auto-bump reads sw-pool,
sw-pool is hand-edited to match the pin, so CURRENT == TARGET and the
cron reports up-to-date forever) and the writer's honest limitation: the
push script writes the record but does not commit it.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
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
triform/chromeless!43
No description provided.