Skip to content

Run headless Orca with bundled Bun and preserve SQLite durability - #22635

Merged
OrcaWin merged 36 commits into
mainfrom
OrcaWin/np-bun-profile-persistence
Sep 26, 2026
Merged

OrcaWin merged 36 commits into
mainfrom
OrcaWin/np-bun-profile-persistence

Conversation

@OrcaWin

@OrcaWin OrcaWin commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator
Files Added Deleted Net
Test 71 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​7960 $\color{#cf222e}{\Huge{\mathbf{−}}}$​318 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​7642
Prod 102 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​5453 $\color{#cf222e}{\Huge{\mathbf{−}}}$​624 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​4829

ELI5

Headless Orca brings its own verified Bun runtime, so users can keep their installed Node version. Existing node orcad.js commands hand off to Bun before opening a profile. The desktop stays on Electron, with the SQLite/background-writer guarantees from #22612.

Base #22612 is merged; this PR now targets main. Ordinary JSON-backend retirement remains next. This extracts the runtime foundation from #16741; managed remote deployment remains separate.

What Changed

  • Pin and hash-verify Bun 1.4.2 with the server, persistence workers, terminal daemon/gate, watcher and required data. Resolve symlinked launchers correctly. Missing, corrupt or mismatched installations return configuration exit 78 before opening a profile.

  • Extend the existing SQLite adapter for Bun while preserving transactions, foreign keys and integer safety. Large write metadata returns exact bigint; explicit undefined bindings are rejected consistently. Read-only WAL handling leaves directory-permission decisions to SQLite.

  • Separate normal startup from strict qualification. Normal startup verifies artifact identity, SQLite writes/backups and Windows process identity; optional terminal/watcher failures can degrade. Build, CI and deployment qualification still exercise both probes. Hash artifacts once in the isolated child and verify its nonce-bound result against the installed version.

  • Tie runtime lifetime to its launcher through IPC. Launcher loss and Windows stops begin bounded graceful shutdown, including early requests. Detaching prevents duplicate POSIX terminal-group signals and escapes the Windows child job. Repeated signals coalesce; a referenced 15-second deadline bounds a stalled drain. Headless POSIX operation ignores SIGHUP; SIGINT/SIGTERM remain the stop contract.

  • Preserve Windows shells through foreground Ctrl-C, with real shell-spawn receipts and fallback, MSYS containment, final output and cleanup. Retry failed resumes, treat suspension failures conservatively, and enumerate jobs containing more than 64 processes.

  • Send SIGHUP for default POSIX terminal shutdown so interactive shells can exit before forced teardown. Explicit signals and the Windows default remain unchanged.

  • Discover POSIX process groups asynchronously and resume only groups this pause stopped, leaving Ctrl-Z jobs suspended. Permission-denied pauses stop retrying and release acquired stops; partial resumes retain their retry obligation.

  • Inspect actual foreground and child processes when Bun reports only the spawn filename, including the in-process fallback. Ordinary programs are visible, login wrappers do not make idle shells appear busy, and background/suspended work still protects close. Failed observations stay conservative and cannot reuse a predecessor's cached result.

  • Cover launch cancellation, early exits and actual Node 18 bundle load/handoff. Preserve bundled search assets, notices, target hashes and executable permissions.

  • Harden future SSH deployment with configured HTTP/proxy handling, progress-based download timeouts, cache recovery, libc fallback detection and structured stop results. It has no production callers.

  • Share native ZIP extraction, honor ORCA_UNZIP_BIN on Windows and remove unused extract-zip. Ordinary desktop builds neither bundle nor download the unused deployment template; explicit template builds remain available.

  • Consolidate the producer-transition predicate, remove redundant Windows resume state and reuse streamed checksum reads. Pause/resume obligations and artifact verification remain unchanged.

Why

Users can move directly from their existing Node installation to a capable bundled runtime without upgrading Node or installing Bun globally. Driver differences stay behind the existing persistence interface.

A trustworthy storage runtime is required at startup; optional terminal and watcher probes already support degraded operation. Separating those checks avoids restart loops on hosts with exhausted watcher resources or slow initial terminal startup. Reusing process inspection preserves close protection when the terminal daemon falls back in-process.

Linked Issue

No linked issue. Builds on merged #22612; focused extraction from #16741.

Visual Proof

N/A — runtime, persistence and packaging changes; no rendered interface changes.

Testing

Current head: 19d4489fa0, rebased onto merged SQLite 82412dab8b on main. All 36 Bun commits have identical patches to the previously qualified f8df2844ad stack; the final source tree exactly matches the expected combined integration. The base adds a reviewed Playwright startup-retry correction; its seven unit tests and both Linux recovery E2E scenarios pass. The full typecheck and 29 integration tests passed on the earlier combined-main tree; final integration checks also pass after the additional disjoint mobile and hook-count-test changes. Fresh CI triggered by the restack is not claimed complete. Independent Codex and Claude Code Opus reviews found no P0/P1 defects in the previous full reviews and no P0/P1/P2 findings in the final cleanup and rebase integration. Existing Bun patches are preserved; only lockfile context already supplied by main and a duplicated base cleanup were dropped.

Coverage Result
Final cleanup 267/267 focused tests across 22 files on the final dependencies. No tests or assertions removed or changed.
Built Bun artifact Rebuilt headless artifact; readiness and 906 tests passed / 16 skipped on macOS ARM with Bun 1.4.2 and SQLite 3.51.0.
Static checks Full Node, CLI and renderer typecheck passed; zero new quality findings across 630 changed files; eight-file lint/format and whitespace checks passed.
New-head native matrix All ten lanes passed, including both glibc-floor and musl architectures. Node 18 handoff passed on standard x64 Mac/Linux/Windows lanes.
New-head full PR CI Run 36215764882 completed successfully on f8df2844ad. All unit shards, static/type, packaging and selected E2E gates passed.
New-head performance contracts All three OS lanes passed, 78 tests each. No failures or reruns.
Historical platform qualification Before cleanup/rebase, all ten native lanes passed: macOS ARM/x64, Windows ARM/x64, Linux glibc ARM/x64, Ubuntu 20.04 ARM/x64 and Alpine/musl ARM/x64. Performance passed on all three OSes. These do not qualify the new head.

Coverage includes worker commit/export faults, launcher death and early stops, actual Node 18 load/handoff, foreground interrupts, Ctrl-Z preservation, slow output, failed resumes and concurrent backup. Default POSIX shutdown uses native shell hangup handling; Bash and Zsh regressions fail before the production fix and pass after it. Fixtures retain their no-leak and timing assertions.

Fresh combined installers published successfully from exact source f8df2844ad, including both PRs and merged SSH fix #22991. Build 36215785431 passed both Mac and Windows jobs. Mac ARM/Intel packages are signed/notarized; Windows is unsigned. Source identity, manifest hashes, referenced asset sizes and blockmaps were verified; binaries were not downloaded or launched.

Earlier full PR CI passed 445 browser cases and 67 app/SSH E2E cases. The pre-cleanup workflow 36212452874 was superseded before completion. SQLite base #22612 retains its documented historical extra-PTY reconnect failure; no causal attribution to #22991 is claimed.

ORCA_BACKGROUND_LAUNCH=1 pnpm build:orcad
ORCA_BACKGROUND_LAUNCH=1 pnpm test:bun:profile --artifact
pnpm tc
pnpm run check:code-quality:changed

Agent-launched apps/tests use background mode. Windows regressions run on Windows; POSIX-only cases skip there.

  • Local behavior and automated regressions exercised.
  • Runtime, database, packaging and Windows coverage added.
  • New-head native and performance matrices passed.
  • Full PR workflow completed on f8df2844ad.

Review

Merge preparation preserved all 36 patches with no conflicts and verified source-tree equality (947eba4d5a31951bd548ddbc0e83b6ca9a980e12). The unchanged Bun code retains its full CI, ten-platform native and three-platform performance qualification; checks newly triggered by the history-only restack are separate.

Suggested order: artifact closure/startup handoff; SQLite adapter; terminal flow control and process inspection; deployment groundwork; failure tests.

The normal-startup and fallback-inspection findings were valid and are fixed. Review also corrected stale process caches, Windows interrupt handling and shutdown races. Base-PR fixes retain durable publication while preserving surviving reattachments and successor terminal identity.

Repeated signals deliberately coalesce: a timing heuristic cannot reliably distinguish an operator's repeat from delayed duplicate supervisor delivery and could truncate the writer drain. The 15-second watchdog supplies the bound.

The AVX2 finding does not apply to pinned Bun 1.4.2: its source documents an SSE4.2 x64 baseline, and downloaded baseline executables match the pinned hashes. No runtime-pin change was needed. Strict qualification remains strict; artifact verification does not rely on a size/mtime cache.

Agent skill upstream boundary

  • Not applicable; no upstream skill-installer resources copied or translated.

Notes

  • macOS 13 remains unqualified: no host is available. Bun uses system SQLite, so newer macOS tests do not establish that floor.
  • Backup cancellation is cooperative during a native Bun SQLite call. The shutdown watchdog remains effective; strict native interruption needs a separate process or upstream support.
  • Managed deployment remains unconnected. Legacy subshell PID migration and stronger incumbent ownership proof are required before connecting it; unproven owners are not signaled automatically. New immutable artifacts intentionally differ from old installs.
  • The Windows stale-owner and hard-link-filesystem limits from Persist profile state in SQLite with a durable background writer #22612 remain. Abrupt crashes can also leave small owned launch scratch directories.
  • POSIX output backpressure uses asynchronous process discovery because this Bun version exposes no supported terminal-read pause API; synchronous resume is limited to teardown.
  • Ordinary JSON-backend retirement and stable-channel update rehearsal remain separate. JSON import/export/recovery remains supported.
  • Tracking, design, research and measurement documents remain local. The existing operations guide is corrected to describe shutdown behavior.

Checklist

  • Small PR — runtime dependency closure and platform support are substantial.
  • Explained behavior, mechanism and alternatives.
  • Visual proof is N/A with reason.
  • Independently reviewed for correctness and performance.
  • Cross-platform, SSH, folder workspace and mixed-version impact considered.
  • New-head native/performance matrices and fresh installer publication passed.
  • Full PR CI completed on f8df2844ad.

@OrcaWin
OrcaWin force-pushed the OrcaWin/np-bun-profile-persistence branch from 561f43f to 9936257 Compare September 24, 2026 11:00
@OrcaWin
OrcaWin force-pushed the OrcaWin/np-bun-profile-persistence branch 8 times, most recently from 78fe4dd to c408d55 Compare September 24, 2026 23:06
@OrcaWin
OrcaWin marked this pull request as ready for review September 24, 2026 23:06

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — full coverage of the 121-file diff at c408d55ed6, plus targeted reads of the surrounding callers and three focused specialist passes.

  • Bundled Bun runtime + handoff — handoffToBundledOrcad, the nonce-keyed profile-state readiness preflight, and artifact identity hashing in src/main/orcad/.
  • Bun SQLite driver — bun-sqlite-database.ts, bun-sqlite-statement.ts, node-sqlite-statement.ts, sqlite-integer-reader.ts, and the SyncDatabase driver selection.
  • Windows Bun PTY — job-object ownership (windows-bun-pty-job.ts), the gate child/launch (windows-bun-pty-gate.ts, windows-bun-pty-launch.ts), the FFI native module, and the runtime/flow-control wrappers.
  • Remote orcad deployment — template materialization/verification, libc detection, remote preflight, and the extracted installOrcadBundle lock lifecycle.
  • Build/packaging — build-orcad*.mjs, watcher/process-tree staging, the zip extractor, macOS template signing, electron-builder wiring, and the new ten-lane Bun CI matrix.

I specifically checked the failure modes most likely to matter here and could not substantiate any: the Bun SqliteStatement binding contract (Bun unwraps a single array argument, so the empty-array binding clears stale state as asserted), VACUUM INTO against the pre-created empty temp every production backup caller uses, suspended-process resume/handle accounting in the Windows job lifecycle, and the .version/readOrcadArtifactIdentity hash agreement. Two latent observations were investigated and ruled non-actionable for this change: Bun's VACUUM INTO refuses a non-empty existing target (Node's backup overwrites) but no caller supplies one, and local-pty-foreground-inspection.ts still passes proc.pid as the shell pid even though the daemon's foreground paths were moved to ptyShellProcessId — unreachable today because the local provider runs on node-pty, where the two are identical.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — incremental delta since the prior Pullfrog review at c408d55ed6: commit 8c5e7ead52 (63 files, +1608/-715), re-read against the full PR diff with three focused specialist passes.

  • Removed the deployment template from desktop packages — deleted sign-mac-orcad-template.cjs and its test, dropped out/orcad-template from electron-builder.config.cjs and the build:desktop/build:release scripts, and moved template verification into build-orcad-template.mjs.
  • Added Windows shell-spawn confirmation — windows-bun-pty-spawn-receipt.ts publishes an atomic pid/error receipt, native-pty-spawn.ts awaits proc.waitForSpawn(), and WindowsBunPtySpawnUnconfirmedError suppresses the PowerShell→cmd fallback whenever a shell may already have run.
  • Made POSIX flow control asynchronous and coalesced — reconcile() re-reads the process table off the event loop and aborts it on shutdown, and posix-pty-process-groups.ts moved off execFileSync onto runProcess/runProcessSync.
  • Hardened shutdown signal handling — extracted installOrcadShutdownSignals, made duplicate SIGINT/SIGTERM/SIGHUP no-ops so the final writer drain can complete, and stopped the Windows launcher from hard-killing a child that already received console shutdown.
  • Repaired corrupt orcad cache entries — findOrcadCachePath recovers a verified .repair-N sibling instead of refusing startup; downloads now use the configured HTTP client and a progress-reset stall timer.
  • Shared ZIP extraction and libc fallback — Windows extracts with inbox System32/tar.exe, and libc detection falls back to getconf/musl-loader evidence when ldd is unavailable.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — incremental delta since the prior Pullfrog review at 8c5e7ead52: commit 35fad32e77 ("support BusyBox terminal process discovery"), 3 files, +329/-44, re-read against the full PR diff with one focused specialist pass on the dialect-probe concurrency.

  • Added BusyBox ps compatibility — src/main/pty/posix-pty-process-groups.ts now routes both async and sync reads through processTableQueries, which tries ps -p + ps -t first and, on an unsupported-selector rejection, falls back to a full-host ps -e -o pid=PROCESS_ID,pgid=PROCESS_GID,tty=TERMINAL_DEVICE_NUMBER. The long =HEADER names are load-bearing: BusyBox sizes each column to its header, so device numbers like 136,1000 are not truncated into another terminal's identity.
  • Serialized the first dialect probe — a process-global psDialect cache plus dialectProbe (waitForPromiseWithSignal) collapses concurrent first reads onto one probe, released in finally; a post-read re-check throws UnsupportedPsSelectionError when another caller has already proven the full-scan dialect, keeping the synchronous teardown path and async readers consistent.
  • Tightened the controlling-tty guard — hasControllingTty now also rejects -, 0, and 0,<minor>, and all ps invocations pin LC_ALL=C with bounded timeout/output.
  • Extended coverage — 201 new unit assertions for dialect caching, rejected-selector fallback, unrelated-failure isolation, shared concurrent probes with independent cancellation, and sync/async dialect sharing; the 16 MiB integration flood test gained a readiness/continue handshake.

I independently confirmed the parts most likely to be wrong: BusyBox 1.36.1 rejects -p/-t with ps: invalid option -- 'p' and accepts the full-scan form while widening columns to the header, and procps-ng 4.0.4 accepts both forms. The specialist pass found no probe leak, no cross-root table mix-up (no await between the psDialect === 'all' re-check and psDialect ??= 'selected'), and no path where an unrelated ps failure (timeout, truncation, signal, permission, or a different rejected option) triggers the full-host scan. The focused unit file passes 36/36.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — incremental delta since the prior Pullfrog review at 35fad32e77: commit 1f3ea8066a ("recover interrupted Bun terminal resumes"), 5 files, +328/-31, re-read against the full PR diff with one focused specialist pass on the new flow-control state machine.

  • Added a resume-retry state machine — bun-pty-process-flow-control.ts replaces the boolean paused with running/paused/uncertain, tracks groupResumeRequired from actually delivered SIGSTOPs, and retries a failed resume every 500 ms on an unref'd timer until a fresh process-table read can release every group. The root pgid is sorted last, so the shell is never resumed ahead of a job group that failed.
  • Preserved the resume obligation through partial failures — a non-ESRCH signal failure inside a resume sweep aborts the sweep before the root and schedules the retry, so a partially stopped tree is never left half released; the fallback now throws instead of root-resuming when groups are required.
  • Cancelled pending work on natural exit — emitExit calls resumeForShutdown() right after exited = true, aborting an in-flight ownership lookup and clearing a queued retry so a late SIGSTOP/SIGCONT cannot target a dead or recycled pid; the Windows job is no longer resumed after exit.
  • Extended tests — the 16 MiB integration flood test now runs with and without a rejected first resume, and new unit coverage exercises retry-on-transient-failure, timer cancellation on pause/shutdown/exit, bounded retries with recovery, root-only suspension, partial-resume re-pause, and natural-exit cancellation.

I traced the synchronous state writes against the async read chains and dispatched an independent pass on the same question; no interleaving was found that loses a SIGCONT obligation, emits a spurious SIGSTOP after resume, or leaves a retry timer firing after exit. The two changed test files pass 39/39 here.

ℹ️ A stopped job group can outlive the shell if it exits mid-resume-retry

emitExit sets exited = true before calling resumeForShutdown(), so the !isExited() guard deliberately skips SIGCONT on natural exit. That is the right trade when the pid may be dead or recycled, and it is not a regression — before this commit no release was attempted on natural exit either. The narrow tail is that a job group successfully SIGSTOPped while a resume retry is still pending (state === 'uncertain') is never released once the root exits. No action requested; noting it only because the retry state machine is new here.

Technical details
# Natural-exit boundary and stopped groups

## Affected sites
- `src/main/daemon/pty-subprocess/bun-pty-process-runtime.ts:68` — `exited = true` is set before the shutdown call
- `src/main/daemon/pty-subprocess/bun-pty-process-runtime.ts:69` — `producerFlowControl.resumeForShutdown()`
- `src/main/daemon/pty-subprocess/bun-pty-process-flow-control.ts:193` — `if (!options.isExited() && state !== 'running')` gates the SIGCONT

## Required outcome
- None. This is informational: confirm the natural-exit no-SIGCONT behavior is the intended trade-off for the new resume-retry state machine, given a stop may have been applied to job groups while a resume retry was outstanding.

## Open questions for the human
- Is there an owned-cleanup path (or an existing tree teardown) that already reaps stopped job groups when the root shell exits naturally, or is that expected to be left to the OS?

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — incremental delta since the prior Pullfrog review at 1f3ea8066a: commits 258c4af954 ("confirm shell suspension before pausing terminal jobs") and 381bb9eadf ("synchronize the Bun terminal fallback fixture"), 6 files, +248/-55, re-read against the full PR diff with one focused specialist pass on the new pause-confirmation state machine.

  • Made pause confirm shell suspension — pause() now sends SIGSTOP to the root synchronously (via numeric os.constants.signals values) and reconcile() only suspends the owned job groups once isPosixPtyRootStopped() proves the root's ps stat begins with T; otherwise the jobs are deliberately left running and state is still recorded as paused. resume() now defers its SIGCONT to a fresh ownership read instead of signalling immediately.
  • Reordered SIGSTOP delivery — signalPosixPtyProcessGroups now signals the shell PGID before the job PGIDs for SIGSTOP (SIGCONT keeps the root last) and aborts the sweep before touching jobs when the shell's own SIGSTOP fails (EPERM throws, ESRCH returns).
  • Added stat to the process-table read — both the selected (ps -p/ps -t) and full-host forms now request the state column, and isPosixPtyRootStopped parses it.
  • Synchronized the Bun flood fixtures — the "discovery unavailable" integration case gates its second flood on a file the test writes so the stability window is meaningful, and the 16 MiB flood fixture gains a stopSignalGapMs dimension that gives Bash time to react between per-group SIGSTOPs.

I could not substantiate a new defect. I verified empirically that BusyBox 1.36.1 accepts stat=PROCESS_STATE on its full-scan form (widening the column to the header, reporting T for a SIGSTOPped process) while still rejecting -p/-t, and that procps-ng 4.0.4 accepts both; the three changed unit files pass here (41/41, 19/19, 24/24). The specialist traced every pause/resume/resumeForShutdown/natural-exit/read-resolution interleaving and found no lost SIGCONT obligation, no spurious stop after a resume, and no resume-retry firing after exit or shutdown.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — incremental delta since the prior Pullfrog review at 381bb9eadf: commit 277c13e055 ("tolerate delayed Windows fixture handle release"), 1 file, +3/-3, test-only.

  • Tolerated late Windows handle release in the Bun terminal fixture — bun-pty-process.integration.test.ts now imports removeTreeSync from src/shared/windows-transient-lock-removal.ts and calls it in runTerminalScript's finally instead of a bare rmSync(directory, { recursive: true, force: true }). On non-Windows it is behaviorally equivalent (same options, no extra retries); on Windows it retries the EBUSY/ENOTEMPTY/EPERM window that a just-exited child or AV scanner can hold.

No production code changed, so there is nothing to re-verify beyond the earlier flow-control review; this commit only hardens test teardown for a failure mode whose assertions had already passed.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@OrcaWin
OrcaWin force-pushed the OrcaWin/np-async-profile-persistence branch from 60cc397 to 6b28239 Compare September 25, 2026 01:17
@OrcaWin
OrcaWin force-pushed the OrcaWin/np-bun-profile-persistence branch 2 times, most recently from db5a835 to 9a2596c Compare September 25, 2026 01:33

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — incremental delta since the prior pullfrog review at 277c13e055: the branch was rebased onto a base that already carries bundled ripgrep (#22396), plus one new commit db5a8350c7 ("integrate bundled search with Bun artifact verification"), 10 files, +180/-51. Re-read against the full 139-file PR diff with one focused specialist pass on the artifact-identity and exec-bit question.

  • Aligned build and runtime artifact identity — computeOrcadFullVersion now prepends orcadArtifactHashPrefix(target) and appends the optional agent-browser bytes, matching readOrcadArtifactIdentity; build-orcad.mjs passes the exact BUILD_TARGET it writes to .build-target and the same browser-name inputs, so the build's .version and the runtime identity can no longer diverge.
  • Restored executable bits after remote upload — installOrcadBundle now runs an executablePermissionsCommand that chmods bun-runtime and ripgrep/**/rg unconditionally and each of the glibc/musl agent-browser-* binaries when present, because SFTP drops modes. Windows hosts skip it. The materializer and template build mark the same files executable on assembly.
  • Integrated ripgrep into the orcad template/materializer — the template build copies the POSIX rg binaries with the executable bit, and artifactSources marks bun-runtime and /rg executable, consistent with the standalone build.
  • Covered the identity contract with a cross-check test — new it.each(ORCAD_BUN_TARGETS) asserts computeOrcadFullVersion === readOrcadArtifactIdentity for all eight targets, with and without the browser, and that browser bytes change the hash.
  • Dropped a now-redundant static-binary guard — verify-linux-glibc-floor.cjs no longer wraps objdump -T in a "not a dynamic object" catch, since readImportedSymbols only runs when !isStatic && !isMuslTarget; a static bundled ripgrep short-circuits before it.

The one residual observation — requiredArtifacts(true) passes bare 'win32', so orcadArtifactFilenames omits windows-process-tree.node — is unreachable because managed Windows SSH deployment is unsupported and orcad never loads that addon, so it is not raised as an issue.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@OrcaWin
OrcaWin force-pushed the OrcaWin/np-bun-profile-persistence branch from 9a2596c to 78a529a Compare September 25, 2026 02:50
@OrcaWin
OrcaWin force-pushed the OrcaWin/np-async-profile-persistence branch from 9622ea0 to 1b2e701 Compare September 25, 2026 02:50
@OrcaWin
OrcaWin force-pushed the OrcaWin/np-bun-profile-persistence branch from 78a529a to 1a07016 Compare September 25, 2026 02:53

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — incremental delta since the prior pullfrog review at db5a8350c7: commit 78a529ac56 ("test: qualify headless shutdown and admission on every Bun target"), 1 file, +2/-0.

  • Qualified shutdown and admission tests under the bundled runtime — config/scripts/run-bun-profile-tests.mjs adds src/main/orcad/orcad-entry.test.ts and src/main/orcad/orcad-push-startup.test.ts to the default Vitest file list, so the bounded-shutdown lifecycle and the profile-admission/startup tests now run on every Bun lane (persistence matrix, glibc-floor container, and musl) instead of only under Node.

Both files exist on the head and are self-contained Vitest units: the shutdown test spies process.on/process.exit and drives installOrcadShutdownSignals with fake timers, and the admission test mocks the runtime/entry surface while using only fs-backed acquireProfileStateMaintenance. Neither pulls a native addon or node:sqlite, so adding them to the Bun runner introduces no runtime-specific dependency.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@OrcaWin
OrcaWin force-pushed the OrcaWin/np-bun-profile-persistence branch 3 times, most recently from 07fbaf9 to bcfa5b0 Compare September 25, 2026 05:05

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — incremental delta since the prior pullfrog review at 78a529ac56: the branch was rebased onto a newer base (prior head 07fbaf9d37, all 16 prior subjects preserved with rewritten SHAs; net PR LoC moved +9805 → +10435, exactly the new commit's +630 net) plus one genuinely new commit bcfa5b0eda ("Harden Bun terminal fallback and producer pause recovery", 20 files, +757/−127). Re-read against the full 149-file PR diff with two focused specialist passes (flow-control convergence; spawn cancellation/leaks).

  • Generalized the producer transition retry — bun-pty-process-flow-control.ts renames resumeRetry/RESUME_RETRY_MS to transitionRetry/TRANSITION_RETRY_MS, retries pause as well as resume (state === (pauseRequested ? 'paused' : 'running')), and moves the root SIGSTOP out of pause() into reconcile() so a failed root stop also reschedules.
  • Required proven job ownership before suspending — signalProcessGroup('SIGSTOP', table, true) now refuses the root-only fallback, so a shell proven stopped cannot leave unaccounted job groups running while the pane is paused.
  • Threaded an AbortSignal through the native Windows spawn — spawnNativeDaemonPty checks the signal before each attempt and after waitForSpawn, races the receipt with waitForPromiseWithSignal, destroys the wrapper on abort, and suppresses the PowerShell→cmd fallback when the spawn was canceled.
  • Extracted runtime spawn selection — new local-pty-runtime-spawn.ts picks node-pty or the Bun adapter once, so the in-process fallback uses the bundled runtime on POSIX and the gated native wrapper on Windows; local-pty-launch-plan.ts skips the node-pty spawn-helper chmod when Bun owns the PTY.
  • Serialized and cancelable same-session launches — new reserveLocalPtySpawn chains same-id spawns so a late Windows shell receipt cannot start a duplicate shell; runCancelableLocalPtySpawn replaces the canceled boolean with an AbortController whose signal is combined with the client's disconnect signal via AbortSignal.any.
  • Retired sessions that exited before the spawn reply — activateLocalPtySession flags a synchronous onExit, disposes the exit listener, skips startup-command delivery, and reports exitedBeforeSpawnReply so a Bun shell that exits before activation is not served.
  • Extended Windows shell identity to the Bun wrapper — processNameIsSpawnFile marks the wrapper's spawn-file name; inspectLocalPtyChildProcesses reads job membership for those processes, and cwd / foreground / signal operations resolve through ptyShellProcessId (gated shells signal proc.signalProcess).
  • New tests — a pause-retry state-machine unit file, pending-native-spawn cancellation/reservation tests, a Windows identity test, and an isolated esbuild + copied-Bun integration test proving the in-process fallback spawns, reattaches and retires a shell without node-pty; the Bun CI matrix now triggers on src/main/providers/** and runs that integration test.

I ran the seven changed unit files against HEAD (73 tests) — all pass. Two independent specialist passes found no reachable leak, double-serve, or hang: POSIX spawns are synchronous (so the un-threaded signal has no cancellation window), the Windows wait is bounded and destroys the wrapper on abort, and the flow-control invariant state === 'uncertain' ⇒ root stopped and not resumed makes the root-running/uncertain combination unreachable. One residual observation was considered and not raised: a pane whose process groups stay permanently unreadable now retries the pause transition every 500 ms rather than settling at paused (pre-commit code did a root-only stop fallback). That is the commit's stated "retain the obligation until ownership is confirmed" behavior, the root is still stopped, and the loop is bounded by the caller's pause failsafe and cleared on resume/shutdown/exit.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@OrcaWin
OrcaWin force-pushed the OrcaWin/np-bun-profile-persistence branch from bcfa5b0 to e1b1074 Compare September 25, 2026 05:37
@OrcaWin
OrcaWin changed the base branch from OrcaWin/np-async-profile-persistence to main September 26, 2026 05:48
@OrcaWin
OrcaWin force-pushed the OrcaWin/np-bun-profile-persistence branch from f8df284 to 19d4489 Compare September 26, 2026 05:48
@OrcaWin
OrcaWin merged commit 6fc3cdc into main Sep 26, 2026
21 checks passed
Jinwoo-H added a commit that referenced this pull request Sep 26, 2026
Picks up #22635's render-harness rewrite so the page terminal render test runs its current form.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
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