electron-builder's CopyElevateHelper re-copies a pristine elevate.exe
from its download cache on every NSIS pack, which clobbered the round-1
SignPath signature in v1.4.129-rc.4 (caught by the evidence gate).
Overwrite the cached copy with the signed one before the rebuild so the
clobber becomes a no-op, and make the evidence gate verify
resources\elevate.exe in every release regardless of whether staging
listed it (the persisted cache can carry an already-signed copy).
- Update package-electron-runtime-contract test: the old test pinned the
pre-inner-signing layout (publish immediately after installer verify);
now pins the new fail-open contract (inner verify + evidence upload
between verify and publish, warn-only gate, continue-on-error chain).
- Budget SignPath waits under the 360-minute hosted-job cap: explicit
timeout-minutes on build, inner-signing wait 4h -> 1h (missing the
window falls through to today's unsigned-inner flow).
- Wrap the evidence gate in try/catch so unexpected script errors cannot
block a release while the gate is warn-only.
- Rehearsal workflow: persist-credentials false, same 1h inner wait.
SignPath cannot deep-sign inside NSIS installers, so unsigned inner PE
files (Orca.exe, node-pty *.node, DLLs) ship with zero AV reputation and
get quarantined by enterprise antivirus (issue #7785).
Add a two-request flow to the Windows release leg: stage unsigned PE
files from win-unpacked, sign them via the windows-inner-binaries-zip
SignPath configuration, rebuild the NSIS installer from the signed tree,
then continue into the existing installer signing request. Every step is
fail-open (continue-on-error + outcome gating): any failure ships the
original installer exactly like releases did before this chain existed.
Add an evidence gate that extracts the shipped installer and verifies
every staged binary is Valid + CN=SignPath Foundation, warn-only until
ORCA_WINDOWS_INNER_SIGNATURE_REQUIRED is flipped to 'true'. Supersedes
the Orca.exe-only gate from #7170 by covering .node and .dll files too.
Rehearsed end to end with test-signing (run 28987534795) and
release-signing (run 28988432001); disarm the rehearsal workflow's
branch push trigger now that both rehearsals passed.
Default the push-trigger policy to release-signing with the release
job's 4-hour approval wait so the production rehearsal can sit in the
manual SignPath approval queue without timing out.
workflow_dispatch requires the file on the default branch; keep the
rehearsal off main by triggering on pushes to this branch that touch
this workflow file, defaulting to the test-signing policy.
Dispatch-only rehearsal of the two-request SignPath flow (sign unpacked
PE files, rebuild NSIS installer, sign installer) for issue #7785.
Never publishes artifacts; verification evidence uploaded per run.
oxlint already fails any file over max-lines that is not suppressed, so the
only way to grow past the budget is to add an eslint/oxlint-disable max-lines
comment or a per-file max-lines bump in mobile/.oxlintrc.json. This adds a CI
gate that freezes the current set of suppressions (config/max-lines-baseline.txt,
355 grandfathered entries) and fails the build when a NEW one appears — with a
loud, actionable message pointing at 'split the file'. Existing oversized files
are untouched; the baseline may only shrink (pnpm check:max-lines-ratchet --prune).
Wired into the root lint script and as a dedicated pr.yml step. Unit-tested
(15 cases) and verified against all three failure paths + clean-tree pass.
Co-authored-by: Orca <help@stably.ai>
* Revert "Preload the daemon windowsHide shim via --require; wrap promisify custom (#7499)"
This reverts commit 8f396badaf.
* Revert "Hide console windows for children of the node.exe-hosted daemon (#7486)"
This reverts commit f0fdd3a716.
* Revert "fix(daemon): relocate daemon host image out of the install-dir kill zone (#7473)"
This reverts commit f4faafa987.
* Revert "fix(pty): keep runtime dirs a surviving daemon still uses (#7463)"
This reverts commit 3cd23a13a1.
* Revert "Relocate node-pty ConPTY runtime outside the Windows install dir (fixes update-time terminal loss) (#7421)"
This reverts commit 509c41e2bf.
Register-PSRepository -Default failed inside the legacy nuget.exe provider
with "Missing option value for: '-source'" on the hosted windows-2022 image,
leaving PSGallery unregistered so the subsequent Set-PSRepository threw
"No repository with the name 'PSGallery'".
Prefer Microsoft.PowerShell.PSResourceGet (bundled with PowerShell 7.4+),
which has PSGallery registered by default and avoids that code path; fall
back to PowerShellGet with an explicit NuGet-provider bootstrap only when
PSResourceGet is unavailable.
Co-authored-by: Orca <help@stably.ai>
* Verify Windows app executable signing
* Isolate Windows signing verifier tests
* Handle direct Windows installer extraction
---------
Co-authored-by: Neil <neil@stably.ai>
* fix(terminal): converge post-spawn PTY size reconcile to fix split-mount column desync
Follow-up to #6644/#6649. Those added a post-spawn PTY reconcile but capped
it at a FIXED 12 requestAnimationFrames whose counter advanced even on frames
where the pane was unmeasurable or the split layout had not yet equalized. When
a tab MOUNTS with a split layout already present (a new worktree opened with the
side split panel on), the real narrow split width settles AFTER frame 12, so the
reconcile gave up while xterm had reflowed narrow and the PTY stayed pinned at
the wide spawn width. The corrective xterm onResize is dropped during the hidden
mount window (isRendererPtyResizeAuthoritative() is false), so process.stdout.columns
stayed wide and interactive TUIs (Claude Code) rendered garbled until a manual resize.
Extract the reconcile into pty-size-reconcile.ts with an authoritative-gated
convergence loop instead of a fixed frame budget:
- While the pane is hidden (onResize dropped), the reconcile is the SOLE corrector:
it keeps polling and forwarding every grid change (its transport.resize bypasses
the visibility gate). Hidden frames never advance the settle counter.
- Once visible AND stable for SETTLE_FRAMES, it hands off to the live
onResize/ResizeObserver path, which reliably catches any later reflow.
- Hard cap (MAX_FRAMES) guarantees termination; mobile-fit/locked frames are
skipped; the reconcile handle is cancelled on dispose.
Harness: pty-size-reconcile.test.ts (14 tests) drives the loop with a deterministic
frame scheduler; the desync-repro tests fail against the old 12-frame logic and
pass on the fix. Adds an e2e "MOUNTS with a split layout present" test.
Caveat: headless Electron does not reproduce this layout-settle-after-rAF race
(the existing golden e2e passes even against the old buggy logic), which is why
#6644/#6649 merged with green e2e yet the bug persisted. The unit test is the
real regression harness; the e2e tests are integration smoke.
Made with [Orca](https://github.com/stablyai/orca)
Co-authored-by: Orca <help@stably.ai>
* fix(terminal): re-assert PTY size on visibility resume to heal stubborn column desync
Follow-up within the same fix: the user reported "sometimes even resizing
doesn't fix it." Root cause beyond the mount-timing race — the renderer forwards
resizes fire-and-forget and dedupes on the size it THINKS it sent, but never
learns the PTY's actual size. A resize dropped main-side (the pane was hidden,
a mobile take-back resize-suppression window, or a provider no-op) leaves xterm
and the PTY silently diverged; a later same-cols layout fires no onResize, so it
never self-corrects.
Expose the PTY's last-APPLIED size to the renderer and re-assert on show:
- New read-only IPC pty:getSize -> ptySizes.get(id) (the size written only when
a resize actually lands or at spawn — the authoritative "what the PTY believes
it is"). Wired through preload (window.api.pty.getSize) + api-types.
- On visibility resume (noteVisibilityResume), the pane re-fits, reads the PTY's
real size, and re-asserts via forwardPtyResize ONLY on genuine drift — so no
spurious SIGWINCH on an already-synced resume (which would jar alt-screen TUIs).
Routed through forwardPtyResize so the authoritative/mobile gates are
re-checked at send time; remote-runtime PTYs (separate viewport channel) are
skipped; overlapping resumes coalesce to one query.
Also register pty:getSize in the registerPtyHandlers removeHandler cleanup block
so re-registration (macOS re-activate / new window) doesn't throw on a duplicate
ipcMain.handle, and make the pty IPC test mock throw on duplicate channels like
real Electron so this class of omission is caught going forward.
Tests: 7 resume-reassert cases (drift / match / null / remote-skip /
mobile-fit-skip / hide-during-hop / overlap-coalesce), all non-vacuous. Full
terminal-pane + pty IPC suites green (1494 tests); typecheck (web+node) + oxlint
clean; e2e desync specs pass against a fresh build.
Made with [Orca](https://github.com/stablyai/orca)
Co-authored-by: Orca <help@stably.ai>
* Stub PTY getSize API and skip redundant Wayland GPU sandbox tests
- Implement PTY `getSize` stub in `web-preload-api.ts` to satisfy API
requirements for the web-preload environment.
- Skip the unfixed Wayland GPU sandbox negative control test if the
target base branch already contains the sandbox workaround.
---------
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Splits the combined Mobile Release workflow into mobile-ios-release.yml (mobile-ios-v* tags) and mobile-android-release.yml (mobile-android-v* tags) so iOS App Store review no longer gates Android. Also fixes iOS signing by passing the App Store Connect API key to build_app so xcodebuild can provision via -allowProvisioningUpdates.
Merged with --admin: the only failing check is the repo-wide pr.yml '@/lib/utils' vitest break affecting all PRs, unrelated to this change.
Adds an ios-build job to the Mobile Release workflow (build + sign + TestFlight upload on a macOS runner via fastlane + App Store Connect API key), and fixes a pre-existing Mobile Checks bug where the mobile typecheck needed root deps for ../src imports.
Merged with --admin: the only failing check is the repo-wide pr.yml '@/lib/utils' vitest resolution break affecting all open PRs, unrelated to this change.