## Why
`Prepare merge` previously promoted a pull request package index into
the live `binaries-abi-v<N>` release before the pull request merged.
That made ABI 39 describe unmerged package state and caused unrelated
resolver and browser gates to consume a canonical ledger that did not
match `main`.
The canceled #934 run also exposed a recovery case: 56 ABI 39 entries
are stale even though the exact current-main archives already exist in
the canonical release. Some PR staging archives have the same
cache-keyed name but different envelope bytes because run provenance is
not part of the cache key. Candidate preparation must repair the ledger
without replacing already-published canonical bytes.
A pre-merge test should prove what can be published. It must not change
what current users resolve.
## New behavior
### Before merge
- Read the canonical index and complete asset metadata through a
mutation-free snapshot while holding the canonical state lock.
- Build and promote archives into a unique candidate release for the
exact PR, run, and attempt.
- When an exact cache-keyed canonical archive exists but its ledger
entry is stale, prefer that canonical asset over a same-name staging
asset.
- Carry the snapshotted SHA-256 and size into the promotion matrix, then
verify both after download.
- Compose and test a complete candidate index.
- Require either an eligible review of the exact PR head or a fresh
`ready-to-ship` application by a current repository maintainer/admin. An
outstanding `CHANGES_REQUESTED` decision still fails closed, and
persistent
label state is never treated as authority.
- Seal the candidate only after the synthetic merge test gate passes.
- Post `merge-gate=success` with the exact candidate release as its
authority record.
No pre-merge job writes, migrates, recovers, replaces, or deletes assets
in the canonical ABI release.
### After merge
A default-branch workflow:
1. verifies the PR head, merge method, exact merged tree, latest
successful merge-gate status, and candidate receipt;
2. holds authority, candidate, and canonical locks in a fixed order;
3. performs one conflict-aware three-way index merge;
4. verifies every retained and candidate archive by immutable SHA-256
identity;
5. copies inert archives before publishing one complete canonical index
transaction;
6. records activation or rejection evidence without hiding a failed
candidate.
Scheduled and manual reconciliation recover interrupted transactions and
retry merged candidates. Cleanup retains open, authoritative, or recent
failed evidence and removes only state that GitHub proves is obsolete.
## Crash and trust handling
- Canonical `index.toml` publication uses an immutable generation,
write-ahead journal, marker commit, and deterministic recovery.
- The pre-merge snapshot accepts only an agreeing committed
marker/generation/live view, or a valid legacy live index, and never
repairs it.
- Duplicate asset names, missing digests, size mismatches, and
post-snapshot replacement races fail closed.
- API reads are paginated and bounded; transient reads retry and
uncertain state is retained.
- Every workflow job whose call graph can acquire the state lock is
audited for effective `actions: read`.
- Workflow contract tests consume complete producer output before
matching, avoiding Linux `pipefail` false failures from early-exiting
consumers.
- A staging retry can omit package builds only after a typed expected
ledger
proves complete package/architecture coverage. The PR release must bind
each
indexed success to one exact uploaded asset, and any stale PR entry must
have
an exact-current canonical supplement. The test gate revalidates both
sources,
verifies and downloads the selected bytes, and resolves from one local
`file://` index. Invalid or incomplete reuse falls back to the normal
build
matrix.
## Scope
This changes package publication control state only. It does not change
Kandelo ABI, package cache keys, or package payloads.
The next successful candidate after this workflow lands will repair the
56 stale ABI 39 entries by copying and verifying the already-published
canonical archives in the isolated candidate, then activating the
corrected ledger after merge. It will not replace canonical archive
bytes.
Archive-envelope reproducibility is a separate known issue. This PR
makes that issue non-destructive by preserving canonical bytes; it does
not trigger a legacy-registry rebuild while the project is migrating
ordinary software to Homebrew bottles.
## Exact-head evidence
- Base: `06afa498d17358cd7e1479fb331f3c4ea179dcb2` (#913)
- Head: `7af64ae3f009984514e2db7adbd9d8319b35d808`
- Tree: `011d8feec4fc3a37c41f57ab706fdcb16bc96ebb`
- History: three purpose commits on current `main`; this PR is intended
for a squash merge.
- Full `./scripts/dev-shell.sh bash
tests/scripts/package-publish-flow.sh`: passed on the exact head.
- Focused xtask index-candidate tests: 10/10 passed.
- Focused xtask staging-reuse tests: 10/10 passed and are enforced by
the publish-flow harness.
- ABI snapshot, header, generated TypeScript bindings, Bash syntax, and
`git diff --check`: passed.
- Live ABI 39 inventory: 210 assets, all uploaded, with no duplicate
names or missing digests.
- Live stale-ledger audit: all 56 exact-main entries select their
existing canonical archive; conflicting staging bytes do not win.
- Live retry audit: `pr-946-staging` is structurally valid for all 71
managed entries, with 57 exact-current entries; `binaries-abi-v39`
supplies exact-current assets for the remaining 14. GitHub Actions run
`29376942848` validated that union and scheduled zero package builds.
- Two independent devil reviews accepted this exact head and tree with
no blocking findings.
GitHub Actions run `29376942848` completed successfully on this exact
head. It materialized and verified the full 71-entry
target-plus-canonical package union, passed host typechecking and the
package-publish flow, built the kernel and test programs, prepared
browser assets, and passed the browser, Vitest, kernel, libc, POSIX,
Sortix, and fork-instrument suites. No package matrix job ran.
`actionlint`, `shellcheck`, and repository-toolchain `rustfmt` are not
available in the declared dev shell and are not claimed.
## One-time bootstrap
`main` at this PR's base does not contain the trusted authorization
verifier,
so no label can bootstrap #946 itself. The earlier label run failed
because the
base-pinned helper did not exist. After this exact head's staging run is
green,
#946 requires a one-time admin-bypass squash merge guarded to this head.
Do not
apply `ready-to-ship` to #946 again. Once this PR is on `main`, future
PRs use a
fresh `ready-to-ship` event for exact-head maintainer attestation.
## Review order
1. `.github/workflows/prepare-merge.yml` and
`.github/workflows/activate-merge-candidate.yml`
2. `.github/scripts/fetch-canonical-index.sh`,
`select-package-archive-source.sh`, and
`download-verified-release-asset.sh`
3. `.github/scripts/verify-merge-candidate.sh` and
`activate-merge-candidate.sh`
4. `scripts/release-index-state.sh`
5. `tools/xtask/src/index_candidate.rs`
6. `.github/workflows/staging-build.yml`,
`.github/scripts/validate-staging-release.sh`, and
`.github/scripts/compose-staging-release-snapshots.sh`
7. `tools/xtask/src/staging_reuse.rs`
8. `tests/scripts/package-publish-flow.sh`
Why
This pull request batches already reviewed fixes so one complete continuous-integration (CI) run can test how they work together before merge. It preserves one commit per purpose, which keeps the history understandable and bisectable.
#907 already landed PHP 8.3.15, ABI 39, and the shared process, VFS,
networking, host-runtime, package, browser-image, Dinit, and Vitest fixes found
during that port. This batch does not replay those changes.
This PR brings the remaining reviewed follow-ups onto one current-main branch
so we can validate and land them together while keeping one commit per purpose.
The focused source PRs remain the review record; their exact heads are listed
below. They were closed only after this batch contained their work and the
combined CI run was green.
What changed
The batch carries the focused changes listed below onto current main. ABI means the application binary interface between programs, the kernel, and the host; VFS means the virtual file system; libc is the C standard library used by guest programs.
Unique work that remains
clearImmediatehandles, nonzero-exitstderr, and configured CORS proxy routing.
assembly, zero-byte copy-back, initial credentials,
mremapmetadata,ENOLCK, and directoryfsync.statfields, align wasm32pthread entry stacks, deterministic fork instrumentation, and SjLj/noexcept
coverage.
evidence, UTF-16 STAT4 accounting, and TestRecover command lifetime.
Exact source heads
3f133f92bd971cc83fecefcd64709ed7b9f13adeclearImmediatecancellation cleanupfc25245984f346a5620998f02f93ad9b85dae80b905dbc0091a40ad9dce04f6ebc3e36e113b40129545048b123d9efabc1474d257329e4e6d154a0f679dd37dbffa2d373988585f954eb45fb162f7c4cce70dc0061ce379d2d50872b48ee0b82908eb8bc224aeeb056829c190680e78bc1ac9a4d68398b546ad38869d71274e773530a9d0860680292235dd1432857531a6969e9ae7d397c2c59406bfb21214d8943e3155d495f9908f8c9ecc2d0e1e06f438805471dc2335abe77c2c696f7bfc1d0cce529710ad72a8bfbcd6ae7f7ebb5799a8e2db3c05bb491cf02mremapgrowth38af72dcaa3c1550f572a63eaa2b7c79c5016218ENOLCKc9f9a1a649c5551f02a24ab5487becccabb6068bfsyncacross kernel, host, and browserc6f4977f3ea2c6bd909e4daaf3f6fbb01c7ca716statfields4b04ff3de6b022549250358f6fe44f02b4475f209e3fd3f6d8ae1693076906f6e462ad6e1f8113a3f758ecb30b92b9c914e950094706f05169bb205e52ba9a72036d2bfc631157c737f91ed61093713da0bc004f569898244f03989558086663d2ba1d78The batch was assembled from those reviewed commits in a straight line, then
condensed from 30 commits to 20 purpose commits. The #780 and #781 changes are
one SQLite recursion/stack-limit policy commit, and the two #926 commits are
one credentials commit. #783 remains represented by one all-mode runner commit
and one truthful-outcome-evidence commit. The final tree is byte-identical to
the reviewed 30-commit batch head. #931's code and test files are byte-identical
to its source head; only its
docs/posix-status.mdcommit diff changes because#929 and #930 update the same document earlier in the batch. #891 was
deliberately dropped after it was consolidated into #936; this PR no longer
duplicates that Homebrew workflow rename.
What was deliberately removed
fork-instrument implementation, MariaDB helper implementation, serialized
image coverage, Dinit production fixes, and other work already on main
through Batch PHP support and bundle ABI updates with their runtime changes #907;
no_mutexworkarounds, fabricated outcome/database evidence, fakehost metadata, synthetic stat block counts, capacity bumps, and broad
pager-fault test omissions;
ABI and package-artifact impact
ABI stays at 39. The ABI snapshot and generated C/TypeScript bindings remain in
sync. The wasm32/wasm64 libc artifacts change for
stat; wasm32 libc alsochanges for pthread stack alignment. SQLite revisions 3 and 4 intentionally
cover the published recursion-limit byte changes. #896, #932, and #933 add no
extra revision because their declared package outputs do not change.
Combined staging must rebuild the affected toolchain and package closure. This
PR makes no performance claim; performance was not measured.
Validation
Exact current head:
822f35ea34cb07e84dac2d24da0505babd16ed7eran on pre-compaction head
260d75d5adc31b327f5591229dbfbb287d395fd6and passed with 84 successful jobs, two expected skips, and zero failures. This
includes 14/14 library rebuilds, 57/57 package/image rebuilds, staged binary
materialization, browser assets, cargo/kernel, fork instrumentation, full
Vitest, browser, libc, POSIX, Sortix, and the aggregate test gate;
ran on that same pre-compaction head and passed the host check and Chromium,
Firefox, and WebKit COI smoke coverage;
scripts/check-abi-version.shpassed throughscripts/dev-shell.sh;lazy-archive, and rootfs-overlay tests;
b3a9a9da574ec7b276e7f61e11f004e578377afa, byte-identical to both thegreen pre-compaction head and the prior reviewed 30-commit tree; only homebrew: name the generic bottle publisher accurately #891
is absent from the earlier batch, because homebrew: publish and verify installable Kandelo bottles #936 now owns it;
fork, libc/POSIX/Sortix, MariaDB, and SQLite validation.
The earlier 31-commit pre-rebuild head
c0ef6ae3368480da8990064593c9c35920fbacb7, which contained the same focusedwork plus #891's workflow rename now owned by #936, also passed:
passed the host check and Chromium, Firefox, and WebKit COI smoke coverage;
passed 14/14 library rebuilds, 57/57 program/image rebuilds, staged binary
materialization, the browser asset check, cargo/kernel, fork instrumentation,
full Vitest, browser, libc, POSIX, Sortix, and the aggregate test gate;
declared URL recovered, and the isolated retry passed without a code change.
fork-instrument tests also passed locally through
scripts/dev-shell.sh.The current head is built directly on
mainat9a7a679195ead9bbdef119830437d5a758566607. Its tree is unchanged by the finalhistory-only rewrite; the new hosted checks will provide exact-head status.
Validation not run
A manual
./run.sh browserpass and the full SQLite upstream matrix were notrerun locally. Performance was not measured, and this PR makes no performance
claim.
Merge and cleanup
Keep the 20 commits in order; do not squash across the remaining purpose
boundaries. An independent per-commit audit found no other valid full squash. The included source PRs are closed as carried into this batch, and
their remote branches were deleted with exact-SHA leases, top-down for the
SQLite stack. This cleanup does not add
ready-to-ship; the normal approvaland prepare-merge flow remain separate.