Skip to content

homebrew: CI-gate the framebuffer smoke (modeset/fbdoom regression guard) (kd-jg94)#819

Open
brandonpayton wants to merge 5 commits into
mainfrom
gascity/kd-1mr/kd-jg94-ci-gate-homebrew-framebuffer
Open

homebrew: CI-gate the framebuffer smoke (modeset/fbdoom regression guard) (kd-jg94)#819
brandonpayton wants to merge 5 commits into
mainfrom
gascity/kd-1mr/kd-jg94-ci-gate-homebrew-framebuffer

Conversation

@brandonpayton

Copy link
Copy Markdown
Member

What

CI-gates the Homebrew framebuffer certification for modeset + fbdoom so a
silent loss of in-browser rendering fails CI -- the class behind the #810 near-miss.
Adds a Playwright spec matching the existing kandelo-modeset.spec pattern,
backed by a shared pour library reused by the standalone runner and the spec.

  • scripts/homebrew-fb-vfs.ts -- shared core (FB_SPECS, FbSmokeResult,
    loadBottleBytes, pourHomebrewFbVfs with DOOM IWAD inject). The kd-k3l9
    runner now imports this instead of duplicating the contract.
  • apps/browser-demos/test/homebrew-framebuffer.spec.ts -- pours the
    modeset+fbdoom Homebrew VFS in beforeAll and, on the new-headless chromium
    channel, fails if rendering regresses:
    • fbdoom -> /dev/fb0: fb bind + pixel writes + non-blank canvas.
    • modeset -> /dev/dri/card0: KMS page-flip commits + scanout dims.
      Chromium-only; skips when Homebrew inputs are absent, so it is a safe no-op
      in browser jobs without bottles and a hard gate where they exist.
  • .github/workflows/browser-demos-ci.yml -- registers the spec.

Verification

  • Playwright spec: 2 passed (--project=chromium) against the kd-0hns tap +
    kd-bry6 bottles + fetched IWAD.
  • Standalone runner (post shared-lib dedup): 5 pass / 0 fail / 0 skip.

Activating the hard gate (input contract)

The spec is env-driven and placement-agnostic:

KANDELO_HB_FB_TAP_ROOT     tap dir with Kandelo/metadata.json
KANDELO_HB_FB_BOTTLE_CACHE dir of <sha256>.tar.gz bottles
KANDELO_HB_FB_WAD          doom1.wad path (fbdoom; freely-redistributable shareware)

The genuine hard gate belongs in the job that builds Homebrew bottles for
modeset/fbdoom (the Homebrew bottle publish/smoke path, which already browser-smokes
hello). That job should export the vars and run this spec. Exact CI placement
is flagged for @brandon
in test-runs/kd-jg94/DISPOSITION.md (given where
Homebrew bottles are produced in CI). Until then the spec safely skips in the
existing browser suites (which prepare registry binaries, not bottles).

Stacking / review note

Stacks kd-0hns -> kd-v3fs -> kd-1mr.5 -> kd-k3l9 -> kd-jg94. Net kd-jg94 delta:
the shared pour lib, the runner dedup, the Playwright spec, and the browser-demos-ci
registration.

🤖 Generated with Claude Code

brandonpayton and others added 5 commits June 30, 2026 10:37
Repair the two defects that made the VFS rootfs/shell input sidecars
nonpublishable: an invalid fork_instrumentation="auto" and local-only
file:// bottle urls.

- scripts/homebrew-generate-sidecars-from-env.sh: package_fork_instrumentation()
  now emits only the sidecar schema enum (not-required/required/disabled/
  unknown), aggregated from per-output package.toml policies; the legacy
  "auto" placeholder and any unknown value can no longer reach a sidecar.
- packages/registry/{16 scoped}/package.toml: declare fork_instrumentation on
  each output (bash/dash/git/vim required; the rest not-required), matching
  whether build-<name>.sh applies wasm-fork-instrument to a forking binary.
- docs/homebrew-publishing.md: document the fork_instrumentation disposition
  values and the publishable https bottle-url requirement.
- test-runs/kd-0hns: regenerated sidecars with corrected fork disposition and
  canonical GHCR https urls. Combined 12-package rootfs/shell tap validates:
  `xtask homebrew-validate` -> packages=12 bottles=12 ok. Disposition and
  passed/failed/skipped outcome lists cover all 16 scoped packages.

Publishable (12/16): dash, git, vim, less, lsof, modeset, nano, netcat, wget,
fbdoom (repaired) + bzip2, xz (adopted pilot). Blocked (4/16, missing Homebrew
Formula): bash, ncurses, curl, nethack.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…r.5)

Run wasm32 in-browser smokes (Chromium/Playwright via BrowserKernel) for the
12 kd-0hns rootfs/shell packages and record the results in their Homebrew
sidecars.

Certified browser_compatible=true (10): dash, git, vim, less, lsof, nano,
netcat, wget, bzip2, xz -- each boots in-browser and passes a package smoke
(exit 0 + expected output). Sidecars regenerated via `cargo xtask
homebrew-sidecars` so provenance shas stay consistent; `homebrew-validate: ok`.

Skipped with reason_code (2): modeset (framebuffer-device-required, /dev/dri),
fbdoom (framebuffer-and-iwad-required, /dev/fb0) -- framebuffer/device programs
not certifiable via the non-interactive terminal smoke, mirroring the Node
framebuffer skips. Encoded as browserFormulaUnsupportedReason().

Effect: homebrew-composite-status browser tier no longer blocks on these 12
being browser_compatible=false; vim-browser-bundle/browser moves skip -> pass.
rootfs/browser now blocked only on bash+ncurses; shell/browser on
bash/ncurses/curl/nethack (kd-1mr.4) plus modeset/fbdoom (framebuffer follow-up).

Adds tailored browser smoke cases (dash/lsof/netcat) and the framebuffer skip
hook. Brings in the kd-v3fs browser tooling required to run the smokes
(browser-smoke/composite-status/smoke-cases/smoke-outcomes runners, the
homebrew-smoke demo page, vfs-planner); those dedupe when kd-v3fs merges.

Evidence under test-runs/kd-1mr.5/ (browser smoke 23 pass/0 fail/2 skip;
composite-status; DISPOSITION.md).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… (kd-k3l9)

Adds a browser framebuffer/device smoke harness and uses it to certify the two
rootfs/shell packages the terminal smoke (kd-1mr.5) could only skip, so the full
12-package kd-0hns rootfs/shell tap is now browser_compatible (homebrew-validate: ok).

Harness:
- scripts/homebrew-package-framebuffer-smoke.ts: pours the Homebrew VFS, injects
  the DOOM shareware IWAD for fbdoom, drives new-headless Chromium (WebGL2), runs
  the program, and asserts framebuffer/CRTC activity.
- apps/browser-demos/pages/homebrew-fb-smoke/: boots the poured VFS with a PTY
  (framebuffer programs query /dev/tty and exit without one) and observes either
  /dev/fb0 writes (fbdoom, via FramebufferRegistry) or /dev/dri/card0 page-flip
  commits (modeset, via kmsAttachCanvas + a stats SAB, WebGL2 mode).

Certified browser_compatible=true:
- fbdoom  -> /dev/fb0: bound 640x400, 1424 pixel-write frames, 249k non-blank px.
- modeset -> /dev/dri/card0: 110 KMS page-flip commits at 1920x1080 via WebGL2.

Sidecars regenerated via cargo xtask homebrew-sidecars (provenance shas consistent).
Effect: modeset/fbdoom removed as shell/browser blockers; shell/browser now gated
only on kd-1mr.4's bash/ncurses/curl/nethack.

Evidence under test-runs/kd-k3l9/ (fb smoke 5 pass/0 fail; composite-status; DISPOSITION.md).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ard) (kd-jg94)

Turns the kd-k3l9 one-shot framebuffer smoke into a CI regression gate for the
modeset + fbdoom browser certification -- the silent-breakage class behind #810.

- scripts/homebrew-fb-vfs.ts: shared core (FB_SPECS, FbSmokeResult,
  loadBottleBytes, pourHomebrewFbVfs with IWAD inject), reused by the runner and
  the new spec. scripts/homebrew-package-framebuffer-smoke.ts imports the shared
  contract instead of duplicating it.
- apps/browser-demos/test/homebrew-framebuffer.spec.ts: Playwright spec matching
  the kandelo-modeset.spec pattern. Pours the modeset+fbdoom Homebrew VFS in
  beforeAll and, on the new-headless chromium channel, fails if rendering
  regresses (fbdoom /dev/fb0 bind+writes+non-blank canvas; modeset /dev/dri
  page-flip commits + scanout dims). Chromium-only; skips when Homebrew inputs
  (KANDELO_HB_FB_TAP_ROOT/BOTTLE_CACHE/WAD) are absent, so it is a safe no-op in
  browser jobs without bottles and a hard gate where they exist.
- .github/workflows/browser-demos-ci.yml: registers the spec.

Verified: spec 2 passed (chromium) against the kd-0hns tap + kd-bry6 bottles +
fetched IWAD; runner 5 pass/0 fail post-dedup. Hard-gate CI placement (which
bottle-building job exports the env vars) flagged for @brandon in DISPOSITION.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

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

ABI v16. 36 built, 6 failed, 42 total.

Package Arch Status Sha
libcurl wasm32 failed
libcxx wasm32 built 309bed52
libcxx wasm64 built 97469b49
libpng wasm32 built da19660c
libxml2 wasm32 failed
libxml2 wasm64 failed
openssl wasm32 built 7147c05c
openssl wasm64 built b6a3f9b1
sqlite wasm32 built 29fd8435
sqlite wasm64 built 5e9ff2df
zlib wasm32 built 90cf6353
zlib wasm64 built 64f7dfc9
bc wasm32 built de85184a
coreutils wasm32 built 27ddf559
diffutils wasm32 built 5f6c2432
dinit wasm32 built a31a9b89
file wasm32 built 54db045a
findutils wasm32 built 8c37f324
gawk wasm32 built 28cac8a6
grep wasm32 failed
gzip wasm32 built 54a71b67
hello wasm32 built 2c152ee8
kandelo-sdk wasm32 built 27ae1cb3
kernel wasm32 built b0cf812f
m4 wasm32 built b2e8d996
make wasm32 failed
mariadb wasm32 built 76b7be27
mariadb wasm64 built 8d87af85
msmtpd wasm32 built 5dec8fca
nginx wasm32 built 11e38a46
php wasm32 failed
posix-utils-lite wasm32 built 7e291a98
sed wasm32 built b5c5f32b
spidermonkey wasm32 built 49ef9232
tar wasm32 built b38257d8
tcl wasm32 built 599fd76a
unzip wasm32 built 01f2d4d4
userspace wasm32 built 355492ee
zip wasm32 built 1e0b11f2
zstd wasm32 built 6a8c2f1f
node wasm32 built 3210297a
spidermonkey-node wasm32 built fa666ecc

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

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