Skip to content

[Homebrew/Browser] Run the bottle-backed shell through a full guest lifecycle - #1083

Closed
brandonpayton wants to merge 11 commits into
mainfrom
homebrew/browser-guest-lifecycle-base-qk044
Closed

[Homebrew/Browser] Run the bottle-backed shell through a full guest lifecycle#1083
brandonpayton wants to merge 11 commits into
mainfrom
homebrew/browser-guest-lifecycle-base-qk044

Conversation

@brandonpayton

@brandonpayton brandonpayton commented Jul 24, 2026

Copy link
Copy Markdown
Member

Why

This bridge connects the bottle-backed, mostly-lazy shell to a complete Kandelo guest lifecycle in both Node.js and Chromium.

The bridge must also be correct at its own exact head. Its lifecycle code imports two deferred-tree modules that contribute to the shell package identity, and it adds a third isolated Chromium proof. The generated package index, declared build inputs, and workflow contract therefore have to describe this final bridge rather than an earlier stack state.

What this adds

  • Keeps the always-needed shell base in the image while exposing bottle-backed package trees lazily.
  • Makes brew available through its public lazy alias instead of adding its full cost to every shell image.
  • Boots the stock guest, uses Homebrew, quiesces and exports its worker-owned root filesystem, reboots from that export, and continues using the persisted filesystem.
  • Exercises the same guest-lifecycle contract in Node.js and Chromium.
  • Declares both deferred-tree source modules as shell build inputs and regenerates packages/registry/program-packages.json from those exact inputs.
  • Replaces a fragile total Chromium-command count with named checks for offline lifecycle rejection, shell acceptance, and MODESET. The inline WHY comment records why every heavyweight browser proof needs its own process.

Why the final corrections belong here

The original lifecycle bridge changed host/src/vfs/package-deferred-tree.ts and imported host/src/vfs/package-deferred-tree-contract.ts. Both files affect the shell package output, so both must be declared before this PR can be an independently reproducible base.

The correction commits only:

  1. Refresh the generated package projection after the first deferred-tree change.
  2. Name the three browser-process isolation contracts instead of counting raw commands.
  3. Add the missing direct imported build input and regenerate the projection once more.

No runtime behavior is being hidden in generated metadata. The Rust generator remains the authority for exactly which dependent package identities change.

Stack and merge requirement

#1081 is restacked directly on this exact head at 362c6dd7e53f7cf3f9213aeb3cf3f7b1fb221d70. After #1079 lands, this bridge head must be preserved with a merge commit so #1081 can be retargeted without rewriting its reviewed content again.

Validation

Run at exact local head 97a4b1d4eb423f77175116e3aa439564f2d3c3f1:

  • Full package-system suite: 125/125 passed across 18 files
  • program-index-check passed
  • program-index-context-check passed
  • scripts/test-package-build-roots.sh passed
  • scripts/test-homebrew-main-shell-closure.sh passed, including all 18 contract subtests
  • bash -n scripts/test-homebrew-main-shell-closure.sh passed
  • git diff --check passed

Fresh PR CI is running against this updated head. This description does not present pending CI as passed.

Embed Bash and its always-needed runtime closure, but leave Homebrew and the selected Formula trees as verified lazy sources. Derive eager and lazy variants from the same package identities so product policy does not create a second recipe.

Record the exact migration locks, Node and Chromium runtime probes, browser download accounting, and the current rollout plan. Ruby-backed brew commands remain intentionally blocked on the ABI 42 dynamic fork-continuation transition and final tap repin before this candidate can ship.
The cutover intentionally turns homebrew-bootstrap into a two-output package and makes it the shell package’s sole registry dependency. Update the combined packaging-contract tests to assert that complete atomic generation and the current shell revision, while continuing to reject every retired registry bundle.
Exercise /usr/bin/brew itself rather than only the canonical target. The test proves symlink resolution finds the registered package tree, fetches the complete verified archive once, materializes every member atomically, and does not refetch on later use.
Regenerate the canonical program package index after the frozen lazy-shell stack changed the closure keys used by lamp, nginx-php-vfs, and WordPress. This restores the package projection freshness contract used before browser assets may resolve.
Add one durable root-image export contract to the Node and browser kernel hosts. The owning worker closes a snapshot gate, drains earlier mutations, rejects concurrent rootfs changes and live processes, and transfers only the root image so lazy descriptors survive a reboot without capturing boot-scoped mounts.

Cover pre-init and non-VFS failures, exact-byte transfer, lazy-state restore, live/tearing-down process exclusion, mutation ordering, and real Chromium/Firefox/WebKit reboot behavior. Keep Vite module-worker reloads on a normal 200 response because WebKit rejects conditional worker revalidation under COEP even when the original response has matching CORP headers.
Exercise the browser worker through its public API so rootfs snapshots are proven to reject live and tearing-down processes, wait for an active lazy-file materialization, and exclude overlapping exports and writes. Reboot the exported bytes and verify the completed mutation is durable while the rejected write is absent.
…romium

Move the generated guest scripts, export/reboot orchestration, and exact VFS input checks into browser-safe shared contracts so both hosts prove the same lifecycle instead of maintaining parallel semantics.

Add an explicitly gated Chromium fixture with immutable URL, byte-length, SHA-256, tap-revision, embedded-plan, and closed-payload bindings. Wire offline admission coverage into CI and document that live execution still requires one coherent published ABI-42 fixture.

Validated with the 38-test focused contract suite, host declaration typecheck, targeted TypeScript checks, Node and browser bundles, the selected production Vite build, and a real Chromium offline admission run.
@brandonpayton brandonpayton added the preserve-head-commit Preserve the exact PR head with a merge commit for publication-pinned artifacts. label Jul 24, 2026
Regenerate the authoritative package projection after the bridge changes the shell-owned deferred package tree. This keeps the bridge head independently buildable before the browser ownership follow-up adds its separate shell input change.
Replace the obsolete total invocation count with named structural checks for offline lifecycle rejection, shell acceptance, and MODESET. The WHY comment records that process isolation belongs to each heavyweight proof rather than to an incidental command count.
The shell imports the split deferred-tree contract through package-deferred-tree.ts, so that contract file contributes to reproducible shell output and must be an explicit build input. Regenerate the authoritative projection in the same commit so this bridge head remains internally exact.
@github-actions

Copy link
Copy Markdown
Contributor

Phase B-1 matrix build status — pr-1083-staging

ABI v42. 68 built, 8 failed, 76 total.

Package Arch Status Sha
icu wasm32 built 48a3ee79
libcurl wasm32 built 8273da44
libcxx wasm32 built 53612e1c
libcxx wasm64 built 986b4977
libiconv wasm32 built b494e26a
libpng wasm32 built e31da77e
libxml2 wasm32 built f8e7709d
libzip wasm32 built 0e020e8d
openssl wasm32 built bdef2279
openssl wasm64 built 11532ba6
sqlite wasm32 built a21f5097
sqlite wasm64 built 1f7a45fb
zlib wasm32 built a826c5a1
zlib wasm64 built 09bd3336
bc wasm32 built 87d9afde
bzip2 wasm32 built 09122fb0
coreutils wasm32 built 72765db8
cpython wasm32 built 314d4763
curl wasm32 built 63cca65e
dash wasm32 built 0b2035e2
diffutils wasm32 built 5b829e0f
dinit wasm32 built 28167e43
erlang wasm32 built fb022926
fbdoom wasm32 built ad115c1c
file wasm32 built 41f1cbea
findutils wasm32 built 9cf821c8
gawk wasm32 built f25ff8e1
git wasm32 built 956b61b3
grep wasm32 built 2b95ab13
gzip wasm32 built c5fea74e
homebrew-bootstrap wasm32 built 8230aaca
kandelo-sdk wasm32 built 5ec342f9
kernel wasm32 built d0e03c4b
less wasm32 built 69fd5aea
lsof wasm32 built 0cbea55d
m4 wasm32 built 746a3cb4
make wasm32 built 8bbaab34
mariadb wasm32 built 89cb71f5
mariadb wasm64 built f6668fed
modeset wasm32 built 8a5f567e
msmtpd wasm32 built 94c0ffb6
nano wasm32 built 48c6e796
ncurses wasm32 built e95f6769
netcat wasm32 built 3d57ef27
nginx wasm32 built cc1c9c86
php wasm32 built 54c56075
posix-utils-lite wasm32 built 81206dd7
ruby wasm32 built b9554136
sed wasm32 built 6265486b
spidermonkey wasm32 built 2c2b1f59
tar wasm32 built d842e794
tcl wasm32 built edae6679
unzip wasm32 built f4ee34b5
userspace wasm32 built 6538ad13
vim wasm32 built 39d28fe5
wget wasm32 built 222061a6
xz wasm32 built 71047565
zip wasm32 built a73d281e
zstd wasm32 built 1e00e7d1
bash wasm32 built 830ea09a
mariadb-test wasm32 built 98b28ac6
mariadb-vfs wasm32 built 8ea599de
mariadb-vfs wasm64 built ffd24483
nethack wasm32 built 35bd109a
node wasm32 built 62a1b6d2
redis-vfs wasm32 built bc95db71
shell wasm32 failed
spidermonkey-node wasm32 built 1fc4b5fe
vim-browser-bundle wasm32 failed
lamp wasm32 failed
nethack-browser-bundle wasm32 failed
nginx-php-vfs wasm32 failed
nginx-vfs wasm32 failed
node-vfs wasm32 failed
rootfs wasm32 built f37ef8a5
wordpress wasm32 failed

Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.

Base automatically changed from emdash/homebrew-abi42-generation-qk044 to main July 24, 2026 21:16
@brandonpayton

Copy link
Copy Markdown
Member Author

Closing as superseded by the exact #1109 lifecycle replay (ee45cb47e through acceptance 32c84abe7). It preserves this PR’s Node/Chromium product goal on current admission authority; this stale stacked head must not merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preserve-head-commit Preserve the exact PR head with a merge commit for publication-pinned artifacts.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant