Skip to content

Add cross-process regression for native pane owner routing #81

Add cross-process regression for native pane owner routing

Add cross-process regression for native pane owner routing #81

name: Packaged Bun runtime
on:
pull_request:
branches: [main]
paths:
- ".github/workflows/windows-conpty-package.yml"
# A Bun pin change in these is a packaged-runtime change: they install the
# Bun that builds and ships the app, so the package proof has to re-run.
- ".github/workflows/build.yml"
- ".github/workflows/release.yml"
- ".github/workflows/native-terminal-soak.yml"
- "electrobun.config.ts"
- "package.json"
- "scripts/fixtures/windows-conpty-package/**"
- "scripts/build-cli.ts"
- "scripts/build-native.ts"
- "scripts/build-terminal-host.ts"
- "scripts/package-native-host.ts"
- "scripts/package-posix-native-host.ts"
- "scripts/verify-packaged-windows-conpty.ts"
- "scripts/verify-windows-app-launch.ts"
- "scripts/verify-windows-conpty-update-archive.ts"
- "src/bun/app-ready-marker.ts"
- "src/bun/index.ts"
- "scripts/native-terminal-host-manifest/**"
- "src/bun/native-terminal-host/**"
- "src/bun/native-task-terminal.ts"
- "src/bun/native-host-runtime.ts"
- "src/bun/task-terminal-backend.ts"
- "src/bun/pty-server.ts"
- "src/shared/resize-protocol.ts"
- "src/bun/__tests__/native-task-terminal.bun-e2e.ts"
- "src/bun/__tests__/native-task-terminal-controller.ts"
- "src/shared/native-terminal-runtime.ts"
- "src/bun/prototypes/detached-pty/**"
- "src/bun/native-terminal-registry/**"
- "src/bun/native-terminal-multipane/**"
- "src/bun/native-terminal-adapter/**"
- "src/bun/terminal-parity/**"
# Windows CLI control transport (seq 1296): both loopback E2E steps below.
- "src/shared/cli-endpoint.ts"
- "src/bun/cli-listener.ts"
- "src/bun/cli-socket-server.ts"
- "src/bun/cli-self-install.ts"
- "src/bun/instance-broadcast.ts"
- "src/cli/context.ts"
- "src/cli/socket-client.ts"
- "src/bun/__tests__/cli-loopback-transport.bun-e2e.ts"
- "src/cli/__tests__/cli-packaged-loopback.bun-e2e.ts"
workflow_dispatch:
permissions:
contents: read
jobs:
package-runtime:
strategy:
matrix:
os: [windows-latest, macos-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 20
steps:
- uses: actions/checkout@v5
- name: Setup build Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: "1.3.14"
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Native shell launch pure tests
run: bun run test:native-shell-launch
# Real loopback proof for the Windows CLI control transport: round-trip,
# two instances, stale record, token rejection, and the loopback-only
# network boundary against this runner's real interfaces.
- name: CLI loopback transport E2E
run: bun run test:cli-loopback-e2e
# The same transport driven through the COMPILED CLI (`dev3.exe` on this
# runner): representative commands, instance selection, stale/corrupt
# records, and the documented app-not-running exit code.
- name: Packaged CLI over loopback E2E
timeout-minutes: 5
run: bun run test:cli-packaged-e2e
# Merged host-image manifest: generator, validator, deterministic assembly,
# additive staging outside the install root, and rollback selection.
- name: Packaged host image + manifest tests
run: bun run test:native-host-image
# Real-runtime lifecycle regression for the persistent native-session
# registry — runs on native Windows + POSIX with the pinned Bun 1.3.14.
- name: Native-session registry lifecycle E2E
run: bun run test:native-registry-e2e
# Seq 1236 force-kills only the recorded host while journal/parser writes
# are active, then proves owned-tree death and token-matched recovery.
- name: Native-session host crash recovery E2E
run: bun run test:native-crash-e2e
# Seq 1237 writer/observer proof. The same real-runtime lifecycle runs on
# native Windows and POSIX: concurrent attach, claim races, reconnect, and resize.
- name: Native-session two-client lifecycle E2E
run: bun run test:native-multi-client-e2e
# Seq 1247 app-restart proof. Two separate short-lived controller processes:
# controller A starts + marks + exits; controller B (a clean process)
# rediscovers and reattaches to the same host/shell/session/pane + state,
# with a deterministic single writer and honest lost-session results.
- name: Native-session app-restart reattach E2E
run: bun run test:native-app-restart-e2e
# Seq 1381 cross-instance owner-routing proof for #1218. THREE separate
# processes against one host: A holds the writer lease and serves the CLI's
# NDJSON protocol, B binds the same pane as an observer and forwards one
# delivery to A, C reopens and counts what reached the PTY. Windows exercises
# the loopback `<pid>.endpoint.json` transport, POSIX the `<pid>.sock` one.
- name: Native-pane cross-instance owner-routing E2E
timeout-minutes: 5
run: bun run test:native-owner-routing-e2e
# Seq 1371 + 1381 PRODUCT proof of the same routing, entered from outside:
# a `message.send` request arrives over the non-owning app's own CLI socket,
# resolves a real task off disk, routes to the owning app and lands in native
# pane-1 exactly once. POSIX only — the pane's shell is `stty -echo; exec cat`,
# which has no PowerShell equivalent, so the Windows leg of owner routing is
# covered by the E2E above instead.
- name: Native message owner-routing E2E
if: runner.os != 'Windows'
timeout-minutes: 6
run: bun run test:native-message-e2e
# Seq 1292 PRODUCT proof: a task's primary terminal driven through
# startNativeTaskTerminal/attach/stop — create, shell round-trip, resize,
# detach, controller restart, observer refusal, owned-tree cleanup with a
# live tmux sentinel, an honest null after cleanup, and the renderer
# transport (pty-server WebSocket bridge with two real WS clients).
- name: Product native task-terminal E2E
timeout-minutes: 5
run: bun run test:native-task-terminal-e2e
# Seq 1254 single-view adapter parity. Drives the shared backend-neutral
# parity corpus against the native adapter on native Windows + POSIX with
# the pinned Bun 1.3.14 (single-view live + pure scenarios; multi-view
# deferred to LAY-003/LAY-004). Expected final line: ALL CHECKS PASSED.
# Completes in ~20s; the step timeout turns a future non-exiting run into a
# fast, obvious failure instead of eating the job's whole 20-minute budget.
- name: Native single-view adapter parity E2E
timeout-minutes: 5
run: bun run test:native-parity-e2e
# Seq 1283 native multi-pane coordinator. Runs the previously deferred
# multi-view scenarios with REAL panes (2 then 6, PowerShell on Windows):
# independent shells, non-crossing output, client-local focus/zoom,
# writer-vs-observer resize, fresh-process reconnect to the same pids,
# single-pane close, and full owned-tree cleanup.
- name: Native multi-pane coordinator E2E
timeout-minutes: 6
run: bun run test:native-multipane-e2e
- name: Explicit Windows shell launch matrix
if: runner.os == 'Windows'
shell: powershell
run: |
& .\src\bun\native-terminal-registry\__tests__\run-windows-shell-matrix.ps1 `
-OutDir "${{ runner.temp }}\dev3-windows-shell-matrix"
- name: Upload Windows shell launch evidence
if: always() && runner.os == 'Windows'
uses: actions/upload-artifact@v5
with:
name: windows-shell-launch-matrix
path: ${{ runner.temp }}\dev3-windows-shell-matrix\
# Seq 1228 live-parser proof. Gates ONLY the deferred path; `callback`
# mode is printed as evidence and is EXPECTED to fail on Windows
# Bun 1.3.14 (the preserved seq 1185 reproduction, decision 146).
- name: Live-parser regression probe (callback vs deferred)
run: bun src/bun/native-terminal-registry/regression-probe.ts both
- name: Live-parser lifecycle E2E
run: bun run test:native-live-parser-e2e
- name: Bundle terminal host entrypoint
if: runner.os == 'Windows'
run: bun run build:native
- name: Build packaged runtime tracer
working-directory: scripts/fixtures/windows-conpty-package
run: bun ../../../node_modules/electrobun/bin/electrobun.cjs build --env=canary
- name: Upload package and proof
if: runner.os == 'Windows'
uses: actions/upload-artifact@v5
with:
name: windows-conpty-package
path: |
scripts/fixtures/windows-conpty-package/artifacts/
# The REAL dev3 Windows package, not the isolated tracer fixture: proves the
# versioned native host image ships inside the final update archive and that
# it stages, launches detached, reattaches, and stops from there with no Bun
# on PATH. Separate job so its ~10 minutes do not eat the matrix job's budget.
windows-app-archive:
runs-on: windows-latest
timeout-minutes: 35
steps:
- uses: actions/checkout@v5
- name: Setup build Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: "1.3.14"
- name: Install dependencies
run: bun install --frozen-lockfile
# postBuild assembles + validates the host image inside the bundle;
# postPackage re-verifies it from the final `.tar.zst` and drives the
# detached lifecycle from the staged copy.
- name: Build the real dev3 Windows package and verify the final archive
run: bun run package:win-archive
# Whole-app proof on top of the native-host lifecycle one: the archive ships
# the desktop executable + bundled dev3.exe + manifest-validated host image,
# and the extracted executable reaches the ready marker and dies completely.
- name: Launch the packaged Windows app and prove clean shutdown
timeout-minutes: 10
env:
DEV3_REQUIRE_WINDOWS_PROOF: "1"
run: bun run verify:win-app-launch
- name: Upload real Windows archive proof
if: always()
uses: actions/upload-artifact@v5
with:
name: windows-app-archive-proof
path: |
artifacts/windows-conpty-package-proof.json
artifacts/windows-app-layout.json
artifacts/windows-app-launch-proof.json
artifacts/*-update.json
# The REAL dev3 macOS and Linux packages. Synthesized bundle trees in vitest
# cannot prove a package ships a launchable host, so this builds the actual
# package, lets postBuild assemble + stage + drive the detached host with no
# Bun on PATH, and then proves a bundled resolver (no source checkout, no env
# override) reaches that image from the packaged runtime.
posix-app-package:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- uses: actions/checkout@v5
- name: Setup build Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: "1.3.14"
- name: Install dependencies
run: bun install --frozen-lockfile
# postBuild → scripts/package-posix-native-host.ts: assemble the versioned
# image into the bundle, stage it outside the install root, then version /
# start / reattach / stop the detached host from the staged copy.
- name: Build the real dev3 package
run: bun run build
- name: Resolve the packaged host image from the packaged runtime
run: bun scripts/verify-packaged-host-resolution.ts
- name: Upload package proof
if: always()
uses: actions/upload-artifact@v5
with:
name: posix-native-host-package-proof-${{ matrix.os }}
path: |
build/*/native-host-package-proof.json
build/*/native-host-resolution-proof.json