Skip to content

Pages: dialogs, error and crash screens, other apps, full screen, print, view source, save, swipe and History as a page - #27

Merged
siyabendoezdemir merged 31 commits into
mainfrom
lane/pages
Oct 11, 2026
Merged

siyabendoezdemir merged 31 commits into
mainfrom
lane/pages

Conversation

@siyabendoezdemir

@siyabendoezdemir siyabendoezdemir commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

The pages lane builds what a page does beyond loading: page dialogs, error, crash and hang screens, links that open other apps, full screen, print, view source, Save Page As, the two-finger swipe and History as a page. It also adds the page keys that come with them (KS-08).

It's built from lanes/pages.md on main (332fb99, then 592096b merged in), and has merged feel and finish-views since (main at 62f6fd6). Against main it changes 89 files (+11754/−217). That's over D30's 9k lines: the lead accepted the build round's 9.9k so the lane could finish AR-10, NV-21 and KS-08's keys, and the two fix rounds added 1.8k.

The builder's reports are in reviews/: lane-pages-report.md (build), lane-pages-fix1-report.md with lane-pages-fix1-without.md (fix round 1) and lane-pages-merge-report.md (the finish-views merge).

What it builds

  • Page dialogs (NV-24): alert, confirm and prompt are Orbit's own tab-modal dialogs over the page. "Leave site?" shows on close and on navigating away.
  • Error screens (NV-13) over the engine's error page, with Try again and ⌘R retrying the failed URL.
  • Crash and hang screens (NV-14): Reload for a crashed tab; Wait or Close page for a hung one.
  • Links that open other apps (NV-19): a dialog naming the app and the site, with "Always allow". A tab opened only to launch an app closes itself.
  • Window full screen (NV-20): the sidebar hidden, with hover reveal. Esc prefers websites (KS-02, D68): a single Esc never leaves full screen; two presses within 1 s, or a hold, do.
  • Print (NV-07): Orbit's print dialog over the page, with the engine's own PDF of the page as the preview.
  • View source (DT-04) in a new tab, read-only, with colouring and line numbers.
  • Save Page As (NV-21), with ⇧⌘S.
  • The two-finger swipe (NV-02) back and forward over the page, with its arrow. Over the sidebar it stays the Space swipe.
  • History as a page (AR-10), at orbit://history/. Under D53 it may run only the pages.history* commands.
  • Follow-ups:
    • chrome fix check 4's N4 (the prompt view after a crash), with N1's note;
    • fix check 3's F4 (a unit test of the frame check);
    • the keys fix check's K1 (a text field in a shadow root);
    • a guard check for the keys review's F11, which didn't reproduce on this base.
  • Built:
    • yes: NV-02, NV-13, NV-14, NV-19, NV-20, NV-21, DT-04, AR-10, KS-19.
    • partial:
      • NV-07: no paper size, margins, scale, pages per sheet or two-sided choices. A history move or a form post right after print() goes at once and takes the dialog with it. A frame's own print() opens the system's dialog.
      • NV-24: quitting doesn't ask, and neither does closing a Peek or a Mini Window yet. A frame's own alert and confirm are Electron's message box, and its prompt returns null (frames have no preload, D40).
      • KS-08: ⌥⌘R comes with NV-23, and ⌃D is DT-06's.
      • KS-02: it now has NV-20's Esc rule; the extensions lane marks the row.
  • Left: K2 (D67), the optional createWindow, NV-23 and the P2s (NV-25, DT-09, AR-06). N3 and K6 are noted as known limits in NV-05 and NV-04.

The page preload (D40, D53)

Each use has a D40 (4) entry in docs/ARCHITECTURE.md:

  • orbit-page:dialog patches alert, confirm and prompt (NV-24).
  • orbit-page:print patches window.print() (NV-07).
  • orbit-page:form-sent is a navigate listener (NV-13). It also feeds the "Leave site?" check that main asks in world 999 (NV-24).
  • orbit-page:swipe is a passive wheel listener (NV-02).

Frames get no preload, so they keep the engine's own dialogs, print and swipes.

Decisions where the spec was unclear

  • Full screen: a single Esc never leaves it; two presses within 1 s, or a hold, do. With prefer Orbit, one Esc leaves.
  • Print's preview is the engine's own PDF of the page (printToPDF), shown in a blob: frame.
  • View Source from a Mini Window opens in a main window, which comes to the front.
  • A crashed background tab shows its crash screen instead of reloading itself.
  • History: ⌘Y reuses the Space's History tab, and an open Library makes way. The page's commands take the profile from its tab, and open only URLs the page was given.
  • Save is File → Save As…; canvas export is left to EZ-11.

Edits in other lanes' files

The report lists each one (§6):

  • windows.ts:
    • the Esc hook skips an Esc the page took;
    • a crashed tab no longer reloads itself;
    • N4.
  • Tabs: closeGuard, mayDiscard, and isActivation exported.
  • Nav: permissions (openExternal), Esc, the page menu, links (F4), focus (K1).
  • Actions, menus and key hints.
  • History: the Archive and the Library's History section.
  • Wiring: the renderer's CSP gains frame-src 'self' blob: for print's preview.
  • Tests: several other lanes' specs. core.spec now reloads a crashed tab itself.

Fix rounds

  • Fix round 1 (307dc62..4418050), on the review's 2 must-fixes:
    • "Leave site?" goes through the engine (D73). ⌘W, closing a window and deleting a Space close pages with close({ waitForBeforeUnload: true }), so every frame's warning counts. Auto-archive and sleep keep a page that warns, without asking.
    • Print:
      • a script's close waits for the print dialog;
      • a navigation right after print() is held;
      • NV-07 is partial where it can't be.
    • Also: D72 (a page dialog takes the keyboard only where its page had it); NV-19's one launch per gesture; the opener's origin in an about:blank dialog; D76's terms.
  • The finish-views merge (e65f412, then 54a2866): MD-06's covers, dialogs above the find bar, NV-19 after Cancel, and feel's .reduce-motion rules.
  • Fix round 2 (08b41a9..6a99a04), on fix check 1's must-fix (D77):
    • One gesture count per page, fed by every frame's input. It's read by the leave guard, NV-19 and pop-ups. So a click in a frame from another site counts, and that frame's "Leave site?" isn't skipped.
    • NV-19: a link to another app uses up the gesture on Open as well as on Cancel.
    • NV-24's notes name the two limits that remain.
    • A test that Reduce Motion stops the page dialogs' and the print dialog's animation.
    • The merge of main at 62f6fd6 (finish-views), and MD-01's note from D78.

Merge gate (D42, local)

Gate r1 ran on this exact head, 6a99a04, on the VPS (Linux, under Xvfb), from 13:55 to 14:38 UTC. It used the lead's gate script:

npm run build && npm run typecheck && npm run lint && ./node_modules/.bin/vitest run
xvfb-run -a -s "-screen 0 1440x900x24" ./node_modules/.bin/playwright test --workers 1 --retries 0 --reporter=line
  • Build, typecheck and lint: exit 0.
  • Unit: 100 files, 1029/1029 passed.
  • E2E: 760 passed, 2 skipped, 0 failed. Exit 0, 42.1 min, load 7.6 → 12.5. The 2 skips are nav.spec's macOS-only key tests.
  • D18: each fix's tests fail on a build without it. The reports list each result (lane-pages-fix1-without.md, and §2 of lane-pages-fix2-report.md).
  • Unverified (macOS only, not run here):
    • full screen on macOS;
    • the real two-finger gesture;
    • the File menu;
    • nav.spec's two macOS key tests;
    • the two frame-typing tests, which need xdotool.
  • Never in a test: real printing, a launched app, or a native dialog that waits for a person.

Review

  • Review (reviews/lane-pages.md, on 307dc62): APPROVE WITH FIXES, 2 must-fix and 15 follow-ups.

  • Fix check 1 (reviews/lane-pages-fixcheck.md, on 54a2866): APPROVE WITH FIXES, 1 must-fix (D77) and 5 follow-ups.

  • Fix check 2 (reviews/lane-pages-fixcheck2.md, on 6a99a04): APPROVE, no must-fix. Fix check 1's must-fix is fixed: its repro now asks "Leave site?" on every close path. The round's new tests fail without each fix (D18). Four follow-ups, none blocking:

    1. A wording fix. The notes say "⌘W and Orbit's other shortcuts" never count as a gesture. A shortcut that goes to the page first does count: by default Ctrl+S on Windows and Linux, and ⌘W if the user sets it to go to websites first. The behaviour matches D77; the wording is in NV-24's note, ARCHITECTURE.md, gestures.ts and a unit test's title.
    2. D77 (4)'s 1 s limit holds only while no DevTools client is attached.
    3. Dead code: isActivation and NON_ACTIVATING_KEYS in tabs/runtime.ts.
    4. Untested rules: the .reduce-motion rules in screen.css and swipe.css have no test yet.

    Routing:

    • Items 1–3 go to the finish-tabs lane, with the builder's note that a pop-up window's own opens (trackPopup) still count only input-event.
    • Item 4 goes to the feel-fix lane.
    • D77's own wording is amended.
  • Bugbot couldn't run on this head (its usage limit).

🤖 Generated with Claude Code


Note

High Risk
Large surface area touching preload security boundaries, keyboard routing, certificate errors, and navigation/close guards across tabs, Peeks, and pop-ups; regressions in Esc, beforeunload, or external launches would affect core browsing.

Overview
This PR lands the pages lane: browser chrome that sits on top of normal page loading—custom alert/confirm/prompt and leave-site flows (NV-24, partial), error/crash/hang overlays (NV-13/14), external app prompts (NV-19), window full screen with Esc rules tied into shortcuts (NV-20, KS-02/19), print with an in-app PDF preview dialog (NV-07, partial), view source and Save Page As (DT-04, NV-21), two-finger swipe navigation via preload wheel handling (NV-02), and History as orbit://history/ instead of only a Library section (AR-10).

Implementation centers on registerPages and expanded src/preload/page.ts IPC (orbit-page:dialog, print, form-sent, swipe), plus architecture docs and regenerated FEATURES.md / feature-status.json (higher built/tested counts). Touch points in other lanes include history routing from archive, internal-page commands for history, page menu hints, and small nav/keys/window fixes noted in the PR description.

Reviewed by Cursor Bugbot for commit 6a99a04. Bugbot is set up for automated code reviews on this repo. Configure here.

siyabendoezdemir and others added 11 commits October 11, 2026 03:41
A page's alert, confirm and prompt, "Leave site?" and HTTP sign-in now show
in Orbit's own small dialog over that page's area only (a tab, a split pane,
a Peek, a Mini Window, a pop-up). The sidebar, other tabs and the command bar
stay usable; a tab's dialog waits while another tab shows. Enter answers,
Esc cancels, Tab stays inside, and the page gets the keyboard back.

- The page preload patches the main frame's alert, confirm and prompt to ask
  main synchronously (orbit-page:dialog), as D40 allows.
- Leave site?: navigations a page's beforeunload stops (will-prevent-unload)
  ask, and Leave starts them again; closing a tab or a window asks each page
  that would warn (the preload's world answers whether it would); auto-archive
  and sleep keep such a tab, and a tab waiting on its dialog.
- Sign-in from the login event, for a server or a proxy.
- Shared edits: TabOps.closeGuard and mayDiscard hooks (tabs/ops.ts),
  maintenance asks mayDiscard, isActivation exported (tabs/runtime.ts),
  rpc.ts and site.ts additions, ARCHITECTURE section 10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…D60)

The page preload listened for beforeunload, pagehide and unload in every
main frame, to ignore a page's dialogs while it goes and to note which
navigation a warning stopped. A beforeunload listener makes the engine run
every page's beforeunload before each navigation Orbit starts, so a busy page
held up Back (keys.spec "goes back at once" took 1.5 s), and an unload
listener keeps every page out of the back-forward cache.

- The patched alert, confirm and prompt now read the event being handled
  (the engine's own window.event and Event.type getters) and return at once
  in the page's beforeunload, pagehide or unload handlers.
- The page's last navigation comes from the Navigation API's navigate event;
  main asks right after the warning, so one that started within 2 s counts.
- New e2e test: a page's confirm and prompt in its beforeunload and pagehide
  are ignored (link and tab close), and a busy page doesn't hold up a
  navigation Orbit starts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A main-frame load that fails shows Orbit's screen over that page's area
only, over the engine's own error page, so the failed address, Reload
and Back stay the engine's: a title, one plain sentence, the site, the
error code and Try again. Certificates lead with Back to safety and keep
Proceed behind Advanced (remembered per profile, host and certificate
until quit). Offline pages load again once when the network returns.
Orbit stops waiting for a server after 120 s (forms being sent are left
alone; the page preload says so over orbit-page:form-sent), and Back
shows the page as it was. The row keeps its title and icon for the site
it showed.

A crashed or killed page shows "This page crashed" with Reload; a page
that crashed in the background shows it when selected, until reloaded
(windows.ts no longer reloads it by itself; core.spec.ts's F11 test and
devtools.spec.ts's DT-14 test follow). A hung page gets "Page
unresponsive" with Wait or Close page.

Page dialogs and screens share one placement module (covers.ts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A mailto:, tel:, zoommtg: ... link no longer reaches the OS unasked. The
engine hands the request to Orbit (nav/permissions.ts refuses it and calls
the pages lane's handler), and Orbit asks in a page dialog over the page
that followed the link: the app's name and icon where the OS gives them,
the site of the frame that asked, and "Always allow <site> to open links
of this type in the associated app" for web sites, kept per profile, site
and kind of link (private profiles in memory only). Cancel is the default:
the keyboard starts there, and Enter anywhere but on Open gives it.

A tab, Peek, Mini Window or pop-up opened only to launch an app never
shows a page: it closes itself once its navigation ends, its opener is
selected again, and nothing goes to the Archive. The question shows over
the page that opened it.

The launch is one function (launchInApp, shell.openExternal); test runs
put a recorder in its place and name the OS's apps through
ORBIT_E2E_APPS, so no test starts an app.

Tests: pages-apps.spec.ts (3), tests/unit/pages-apps.test.ts (8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…prefers websites (NV-20)

Toggle Full Screen (Cmd+Ctrl+F; F11 and Alt+Shift+F on Windows and Linux; View menu on
macOS; the command bar) hides the sidebar, which the left edge brings in over the page, and
docks it again on leaving unless the user chose meanwhile. Esc in a page goes to the page
first; a second press within a second, or holding it, leaves full screen. Exit Full Screen
prefers websites by default and can prefer Orbit in Settings -> Shortcuts (KS-02, D68). A
video's own full screen stays Chromium's. The Esc that leaves does not stop a load.

Other lanes' tests updated for the hidden sidebar: SB-19 (chrome.spec) and KS-20 (keys.spec);
keymap audit rows added for the two actions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cmd+P / Ctrl+P, File > Print, the command bar, the page menu, a Peek's or
a Mini Window's Cmd+P and the page's own window.print() open a print
dialog over that page only: the page as it prints (the engine's PDF in the
PDF viewer) beside destination (Save as PDF, the OS's printers), pages,
copies, layout, colour, headers and footers and background graphics. Esc
closes it wherever its keyboard is, and the page is left as it was. The
next dialog starts from the last one's choices until Orbit quits.

One function sends a job out; test runs record each job instead and take
their printers from ORBIT_E2E_PRINTERS, so nothing prints or asks where to
save. Covers now know a pooled view is ready by its own load (a preview
frame can keep isLoading() true), and take the keyboard just after the
page's own focus change, so a dialog has it again when its tab comes back.
KS-19 is now complete: the print dialog was its last overlay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
⌥⌘U (Ctrl+U), the command bar's View Source, the page menu and the macOS
menu open the page's own address as view-source: in a new tab, shown at
once. One entry for every caller (src/main/pages/entry.ts): a Peek's
page opens its own source, and a Mini Window's opens in a main window
that comes to the front.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A horizontal two-finger swipe over a page that doesn't take it slides an
arrow in from that edge of the page card, following the fingers 1:1; let
go once it's fully in and the tab goes back or forward, as the buttons do.
The page gets the swipe first: a strip that can still scroll that way, or a
page that uses the wheel, keeps it. Over the sidebar it stays the Space
swipe. The page preload's isolated world watches the wheel (Electron's
input events carry no wheel deltas) and tells main on a new channel,
orbit-page:swipe, for the lead to log under D40 (4). On macOS it follows
the system's "Swipe between pages" setting; the real gesture is for a
person to check there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
orbit://history/ shows the Library's History section, every visit of
the tab's profile, by day, with search. ⌘Y (Ctrl+H), Archive → View
History and the command bar show the Space's History tab, or open one;
an open Library makes way, and a Mini Window's ⌘Y shows it in the
latest main window. The page loads its list again when its tab shows
again (main says so: a hidden tab's page stays visible).

The page runs only pages.history* (D53): each takes the profile from
the page's own tab and opens only pages it listed. The Library keeps
its History section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the command bar (NV-21, KS-08)

The page menu's Save Page As… becomes an action, page.save: ⇧⌘S on
macOS and Ctrl+Shift+S elsewhere (⌘S is the sidebar's), File → Save
As… (macOS), the command bar's Save Page As… and the page menu, which
shows its keys (KS-18). The OS save dialog opens from the Downloads
folder, named after the page; a web page saves as a single file or its
HTML alone, and only a local page whose frames are all local saves
complete (D49), as before. A Peek's or a Mini Window's page saves
itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eck)

- N4 (chrome fix check 4): a permission prompt whose view crashed leaves
  the window until its page has loaded again, and the page gets the
  keyboard back if the prompt had it; then the prompt shows again, still
  asking (windows.ts).
- F4 (chrome fix check 3): the Option-click decision is one function,
  altClickOpens (shared/link-routing.ts), with a unit test of R2-F2's
  frame check.
- K1 (keys fix check): a text field inside open shadow roots counts as
  one for the page watcher, the focus mirror and the Cmd+Left/Right check.
- Keys review F11: not reproduced on this base. archive.spec.ts now reads
  main's focused web contents (a page's document.hasFocus() stays true
  while the Library has the keys) after Cmd+W and after Esc from the
  Archive and from History.
- Notes: NV-09 (N1: the toast shows only where Orbit itself refuses),
  NV-05 (N3's known limits), NV-04 (K6's known limit), NV-15 (N4),
  KS-16 (K1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: 5aee9e7d-e9e5-4be3-8b6c-2787589d9cf7)

…ow or a Space, and for auto-archive and sleep (NV-24, D73)

Closing a tab, a window or a Space now closes each page that has had a
user gesture through the engine (webContents.close with
waitForBeforeUnload), so every frame's beforeunload runs, as when
Chromium closes a tab. A page that warns stays (will-prevent-unload),
and Orbit shows its tab and asks "Leave site?": Leave closes it, Cancel
keeps the tab, the window or the Space. Auto-archive and sleep let a
page go the same way and keep it, without asking, when it warns; they
don't try it again until it navigates or gets a new user gesture.

The preload's beforeunload probe is gone: Orbit runs no page's
beforeunload of its own, and no timeout counts as "no warning"
(review follow-ups 4, 7 and 8). Deleting a Space waits for its pages
(spaces.delete is async; tabs.letGo). The tabs runtime gets unload(),
which keeps a page's history for its tab while the page goes.

Tests: a same-origin frame that warns, after a click in it, against
Cmd+W, closing the window, deleting the Space, auto-archive and sleep;
a page that warns from its main frame still asks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: f2f2694b-9a26-4d40-a031-d2e8e29f2fb3)

…r the print dialog (NV-07)

A page that writes a pop-up or a new tab, prints it and closes it at once, or prints and then
sets location.href, lost the print dialog with the page. Chromium's print() blocks the script
until its dialog closes; Orbit's dialog is its own view, so the page preload now holds the
page's window.close() and the navigation it starts (push, replace, reload) while the dialog is
open, and lets them go on when main says the dialog closed. The navigation goes on to the same
URL and a new history entry, as it would have.

orbit-page:print is now sendSync and replies whether the page has a print dialog open;
orbit-page:print-closed (main to page) is new, and the preload patches window.close (D40 (4)).
A form the page posts or a move through history right after print() isn't held: NV-07 is
partial, with these and the missing print settings named in its note.

Tests: the pop-up, new tab and print-then-location.href cases (REPRO J). Without the fix each
fails: no print dialog shows (pages-print.spec.ts :272, :289, :307).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: 778269b8-beb1-4eb8-83de-b81b2417c00f)

siyabendoezdemir and others added 6 commits October 11, 2026 11:03
…d it (D72)

A page could time a confirm() to catch keys meant for Orbit: the dialog took the keyboard from
the find bar or a sidebar field (a tab being renamed), and the user's next Enter answered the
page. A dialog now follows the screens' rule: it takes the keyboard when it shows over the page
the user is on only if the page had it. The find bar, a sidebar field and the address field keep
theirs; the dialog takes it once the user clicks it or the keyboard next goes to the page.

Tests: the rename field and the find bar keep their keys while a timed confirm() shows (review
REPRO G and H); the dialog then takes the keyboard. Without the fix both fail: the dialog has
the keyboard as soon as it shows (pages-dialogs.spec.ts :172, :197).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sture (NV-19)

With Always allow on, nothing limited launches: one click and a timer that followed a mailto:
link 20 times opened the mail app 19 times (review REPRO B). As in Chromium, each link to another
app now uses up its page's user gesture (a mouse press or a key in the page, counted as the tab
runtime counts them), and an always-allowed link opens the app only with a gesture no such link
has used yet.

It doesn't use the tab runtime's consumeGesture, as the review suggested: a target=_blank link to
the app has already used that gesture to open its tab (NV-09), and the engine names the opener as
the page that asks, so Always allow would never open such a link.

Test: one click, then a timer that follows the link 20 times: the app opens once, and again on
the next click. Without the fix it fails: 22 launches instead of 3 (pages-apps.spec.ts :162).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (NV-24)

A tab or pop-up that its opener opens empty (about:blank) and scripts said "This page says" and
named no site, though the page has its opener's origin. The dialog's title now names the asking
page's site from its origin when its address isn't a web one, as Chromium's does: an
about:blank page its opener writes into names the opener's ("<host> says"); a data: or file:
page, with an origin that names no site, still says "This page says".

Tests: an e2e test of an empty tab and an empty pop-up that its opener has ask confirm() (review
REPRO I), and a unit test of the title from an origin. Without the fix the e2e test fails: "This
page says" (pages-dialogs.spec.ts :219).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…'s main frame (review follow-up 13)

Frames have no preload, so e2e can't send from one. A unit test with a fake senderFrame sends
the dialog, print, swipe and form-sent messages from a frame and from the page's main frame: a
frame gets the engine's answer at once and opens no dialog, opens no print dialog, shows no
swipe arrow, and can't take the page's form off the load timer.

Without the frame checks (in a scratch copy) each of the four cases fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y-page check takes D46 rounds (review follow-up 7)

Two checks could fail under load:
- Full screen: the second Esc must come within a second of the first, and polls ran between the
  two presses. The presses that must be paired now go in one call, with nothing between them.
- The busy page: a navigation Orbit starts on a page kept busy must start within a second. It
  was measured once; it is now judged on the best of up to three rounds (D46).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(review follow-ups 10, 15)

NV-05: "text as text" holds for characters on the keyboard's own layout; a held character that an
auto-type tool maps onto the keyboard on the fly, which Chromium names "\u0000", is lost (N3's
third case). NV-02: the swipe isn't offered over a Peek's, a Mini Window's or a pop-up's page,
where it does nothing; the spec doesn't say.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: 1b5ce9af-444a-4fc3-8702-3006b13ae3bc)

siyabendoezdemir and others added 6 commits October 11, 2026 11:27
…ane/pages

Conflicts, each side kept:
- src/shared/site.ts: the pages channels (form-sent, dialog, print, print-closed, swipe) and
  finish-views' screen-share channel (D69).
- src/preload/page.ts: one patchPage runs both patches, each with the built-ins it takes up front:
  the dialogs, print() and the close wrapper (NV-24, NV-07, D76), and the screen-share watch (D69);
  its arguments are the lane's, then screenShared.
- src/main/nav/page-menu.ts: the page menu keeps calling the pages lane (savePage, printPage,
  viewSource); finish-views' withDialog on its old Save path goes with that path (the Save dialog
  is wrapped once, in save-page.ts, in the next commit).
- docs/ARCHITECTURE.md: the preload's patch list names D69's and the lane's built-ins; both sides'
  channel entries; the History internal page note.
- docs/feature-status.json: per key; NV-05 and NV-15 changed on both sides and keep both notes.
  FEATURES.md regenerated.

With feel (from main): the lane's dialog, print, screen and swipe stylesheets key their reduced
rules off the reduce-motion class, and time on feel's tokens (reduced-motion-guard.test.ts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd of Save Page As… and Save as PDF (MD-06)

While a cover (a page's dialog, the print dialog, an error, crash or hang
screen) is on screen, its window counts as showing a dialog in
dialog-watch; the note ends when the cover leaves the screen. Save Page
As… and Print's Save as PDF wrap their save dialogs in withDialog; the
page menu's Save path goes through savePage, so nothing is wrapped twice.

pages-player.spec.ts: the player moves to the nearest clear corner while
a page's confirm, the print dialog and a crash screen show, goes home
while the dialog waits off screen in a background tab, and comes back
when each closes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…bar, in a tab and over a Peek (PK-11, NV-24, D72)

WindowManager.keepAboveTools() marks a view that stays above the page
tools wherever either goes: showTools() places the tools under such a
view (with `top`, over a Peek's page, only one above the overlay band),
and placeAbovePages() puts such a view above the tools when they are
under the ceiling. Page dialogs and the print dialog ask for it; error
and crash screens don't. The find bar keeps the keyboard it has under
D72's rule.

pages-dialogs.spec.ts: a dialog in a Peek shows above the find bar
there, also after the bar is placed again; the bar keeps its keys, and
the dialog takes them when the bar closes; the Peek stays open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…print() opened the dialog (D76)

A print session notes whether the page's own window.print() opened it
(`byPage`). Main's sync print handler still answers at once, waiting on
nothing; it now replies true only for that page's own dialog, so a
print() while a dialog that ⌘P or a menu opened shows returns at once and
holds nothing, as Chromium's does. print-closed, with no data, goes only
to the page that printed.

pages-print.spec.ts: the page's print() while a ⌘P dialog shows, then a
navigation, goes on at once and takes the dialog with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…with a new gesture; a click in a cross-site frame counts (NV-19)

A page whose question the user answered Cancel (or Esc) asks again only
after a new user gesture in it, as in Chromium; a link it follows before
then is dropped. A mouse press in any of the page's frames now counts as
its gesture: an out-of-process frame's input reaches main only as
before-mouse-event, not input-event (so an always-allowed frame's click
opens its app too). Test runs record what came of each link
(__orbitPages.appLinks: asked, opened or dropped), so tests wait on the
handler instead of on time.

pages-apps.spec.ts: after Cancel, a gesture-less link asks nothing, a
click asks again, and after Esc the same holds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… print reply, NV-19 after Cancel; regenerate FEATURES.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: e2dee8cf-73b5-4a22-bfd3-ddcfc7144222)

siyabendoezdemir and others added 6 commits October 11, 2026 13:43
…ture (D77 (1))

One helper (src/main/pages/gestures.ts) keeps each page's gesture count, fed by every frame: a
mouse-down from before-mouse-event or input-event (one press counts once), a key from
before-input-event that reaches the page (not one Orbit takes as its own shortcut, so ⌘W never
counts for the page it closes; nor Esc, a modifier alone or a held key), a tap. The leave guard
(NV-24), links to other apps (NV-19) and the pop-up rule (NV-09: tabs/runtime.ts, its listener
only) read it.

Tests, with a frame from another site (127.0.0.1 in a page on localhost) clicked through
frameLocator and typed in with the real keyboard (xdotool; skipped where there is none): ⌘W, the
window, the Space, auto-archive and sleep; NV-19 after a key in the frame; a pop-up opened by a
click in the frame. A unit test covers the count's rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…swer, Open or Cancel (D77 (2))

Once a page has asked (or an always-allowed site opened its app), its next link to another app asks
or opens only after a new user gesture in it. Before, only Cancel used the gesture up, so after Open
a page's timer could ask again at once (fix check 1, follow-up 4).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…int dialog's animation

With the setting off each card's computed animation-name is its fade-in; with it on, none (FL-28;
fix check 1, follow-up 3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o limits it names

NV-24's note: a gesture in any frame counts, ⌘W and Orbit's other shortcuts are none; the engine's
close leaves a page that auto-archive or sleep keeps with a user activation; ⌘W on a busy page that
has a beforeunload listener waits for the engine, up to its 1 s limit. NV-19's note: after any
answer, Open or Cancel, a page asks again only with a new gesture. ARCHITECTURE.md's leave-page and
app-link paragraphs say what the shared gesture count is and who reads it. FEATURES.md regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts: docs/feature-status.json (MD-06 keeps the lane's note on Orbit's covers, MD-07 takes main's D75 sentence) and FEATURES.md (regenerated).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n the player (D78)

The hidden div the size of the frame's viewport under <html>; when the frame's own script puts a
same-site frame's video back, one possible "ResizeObserver loop completed with undelivered
notifications" error event, and with it the page's own observers of <html> or <body> get the
final size a frame later. FEATURES.md regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: 562cec78-5073-4218-9d51-667fe42b3743)

@siyabendoezdemir
siyabendoezdemir merged commit bf3fc40 into main Oct 11, 2026
1 check passed
siyabendoezdemir pushed a commit that referenced this pull request Oct 11, 2026
docs/feature-status.json takes main's rows, pages' notes included, with the 74 "feel" marks put back. FEATURES.md is regenerated: 472 spec'd, 276 built (77 partial), 356 tested, 74 feel right.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
siyabendoezdemir added a commit that referenced this pull request Oct 11, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
siyabendoezdemir added a commit that referenced this pull request Oct 11, 2026
Conflicts:
- src/main/tabs/runtime.ts: both. Main's letGo hook (NV-24), and finish-tabs' recentSwitch with
  cancel and the onControlUp comment (TB-05).
- src/shared/rpc.ts: both. finish-tabs' toasts view (SB-13, SP-02) and main's dialog, screen,
  print and swipe views.
- tests/e2e/keys.spec.ts: both imports (FOCUS_IS_EDITABLE, switcherOf).
- tests/unit/keymap-defaults.test.ts: the comment drops both built features (blank window; save
  page and full screen keys).
- docs/feature-status.json: per key, the side that changed it; KS-19 is main's (yes, with full
  screen and the print dialog) plus finish-tabs' row menus (TB-14).
- FEATURES.md: regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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