Repository navigation
sync: upstream a45bd06eac into swaplabs/main - #47
Merged
Merged
Conversation
* fix(session-history): freeze scan workload before checking candidates * Show per-agent Session History reading progress * Keep reduced-motion behavior in progress primitive * test(session-history): handle native fixture path separators * test(session-history): control bucket fixture enumeration order * test: cover finished empty history progress rows * test(session-history): preserve scoped fixture timestamps * fix(session-history): repair integrated test and locale catalog * ci: refresh history checks against current main * ci: refresh history checks after catalog repair
…mark reach a server's own layout (dark, layout-owner build only; stacked on stablyai#31714) (stablyai#31869) * wip(h5c-1): server workspace layout intents go to the server's main; positions per stream * wip(h5c-1): e2e without a cast * fix(h5c-1): a routed move never moves here; routed callers read the server's stream; a restarted main starts its positions over * fix(h5c-1): layout-apply-send back under its line limit * test(h5c-1): a routed answer reaches the handler with the server's stream key * fix(terminal): a CLI or phone close through main keeps a pinned tab, as the window-era close did * feat(terminal): main applies phone closes, renames, pane titles, sleeps and agent-launch tabs itself, with or without a window (layout-owner build) * fix(terminal): a tab close through main also ends the tab's dormant SSH relay session; agent-launch tabs main writes keep the window's focus rule, prompt and outcome (layout-owner build) * feat(terminal): main starts a new tab's first terminal under the window's ids, and the pane attaches to it (layout-owner build) * test(terminal): tests that counted the window's create calls or publications see main's start of a new tab * fix(terminal): an account-switch restart binds only into a pane main's layout holds, with no window tree (layout-owner build, L197) * test(terminal): the new-tab start tests hold no type assertions; the start's ledger row is L252 * fix(terminal): a new tab's pane attaches to any terminal main binds it to, and a failed start keeps the tab's startup * test(terminal): a Claude account-switch restart's tests draw the pane main holds * fix(terminal): a launch pane main takes back still tells the window why, which drops its hold and prompt; a rename through main answers the name it stored (layout-owner build) * fix(terminal): a new tab another owner's terminal won attaches to it, and a failed start's startup never runs twice * fix(terminal): main's pane close reads its stop result as a type only, so no runtime module loads before its base class * fix(terminal): a phone's close through main drops the closed rows from what phones list at once, not at the window's next publish (layout-owner build) * chore(terminal): mark the phone-close row drop interim (ledger L260) * test(worktree-create): a new local tab's startup counts as run when main starts it (layout-owner build) * test(worktree-create): record main's starts without a type assertion * fix(terminal): a tab closed before main declines its start gets no startup back (layout-owner build) * fix(terminal): the window's new tab starts in main when its own window asks over IPC, which labels itself a client (layout-owner build) * feat(h5c-2): a paired desktop's writes to a server workspace its frames draw land in that server's main (layout-owner build) - Routes setTabProps, setChatPane and non-terminal renameTab to the server's main as layout.apply; closes, starts, sleeps and terminal names keep the RPCs that main now applies (session.tabs.close, terminal.close, terminal.split, session.tabs.createTerminal, terminal.rename). A window-style closeTabs is never routed: main takes it as already stopped and stops nothing. - A close the server refuses (a pinned tab) redraws the workspace from the server's frames, so the window's optimistic drop never outlives the answer; same for a refused pane close. - A frame-drawn workspace keeps none of the mirror's ledgers (L240): no tab-id mappings, close or focus intents; they stay only for servers without layout.intents.v1 until the Phase 2 cutoff. Its pane-geometry push is skipped (it goes as intents); pane renames still push. - e2e: paired-desktop-server-layout-writes covers close (layout, session.tabs, terminal stop), rename, split and new tab on a windowless switch-on serve. * fix(h5c-2): an undelivered close of a frame-drawn tab is held for replay; a launch-agent clear stays off the server route * refactor(h5c-2): the undelivered-close test moves to its own module, keeping the lifecycle file under its line cap * fix(layout): a paired desktop's pane detach, handle-less split and default-tabs mark on a server workspace go to the server's main (layout-owner build, L272/L276/L275) * fix(layout): a pane a paired server's main detached takes the terminal the server's frame drew, not the desktop's possibly stale one (layout-owner build, L272) * test(layout): the detach test resets the drawn layout after each case * test(layout): drop the in-test reset the afterEach now covers
* feat(native-chat): a Pi chat shows the turns made outside it When a Pi chat's agent opens its conversation, Orca asks Pi for the entries saved after the point the chat last accounted for (get_entries since that entry id) and adds the terminal's turns once, in Pi's order, under the "Continued outside this chat." divider. That point is saved on the conversation handle after each chat turn and at each open. When the chat's own unsaved work and the terminal's share a suffix that can't be split (Orca died mid-turn), that suffix is skipped rather than duplicated, and later terminal turns show normally. A Pi reply over the 8 MiB line limit now fails only the optional read that asked for it instead of ending the chat. * refactor(native-chat): share the catch-up open runner across agents The Codex catch-up's agent-neutral parts move to one module: the open-time envelope (its own deadline and cancellation, never gating the open), the bounded staged batch, the single settlement commit that re-checks the journal before writing, and the "Continued outside this chat." divider. Codex keeps only how it reads its saved turns and what the chat already holds. No behavior change; the other agents' catch-up builds on this instead of copying it. * refactor(pi): catch up through the shared catch-up runner instead of a copy * chore: remove unrelated pnpm executable metadata * refactor(native-chat): the catch-up runner reads the chat's view only when the agent asks * refactor(pi): read the chat's view through the runner's view() * chore: remove regenerated pnpm executable metadata * fix(native-chat): the catch-up deadline also bounds waiting for its commit to be written A journal write barrier that never settled after the import was admitted held the provider's open past the catch-up deadline. The wait now ends with the deadline or the open's cancellation, like every other step. * test(pi): check Pi's session entry ids and get_entries since against the pinned real Pi * test: type the history catch-up sink fixture without assertions * fix(native-chat): bound and revoke history preparation * test: the runner's journal fake answers the cursor Pi's view reads * feat(native-chat): validate expected saved items during history catch-up * fix(pi): preserve outside history and optional read recovery * test(pi): fail RPC smoke promptly when the child stops
…i#31596) * refactor(pty): one commit step for both terminal start lanes The window's pty:spawn commit and the host runtime controller's commit were two copies of the same job (ownership, binding save, registration, size, hidden mark, publication, reservation settle), so every fix had to land twice. Both lanes now call one commitPtySpawn and supply what differs as data: the binding each lane builds, its registration facts, pane key and aliases, the Codex launch env and memory session id. Three inputs still select behavior: hiddenDelivery (the renderer-scoped mark is refreshed here; the runtime-owned mark stays at the host runner's await boundary), earlyExit (the window drains an exit during start, the host throws) and joinPayload (what reservation joiners and the caller receive). One publication order for both lanes: note commit, Codex pane account, renderer hidden mark, handle, size set with reflow, old-id size cleanup, serializer readiness, restore records, command detector, telemetry, pane key and aliases, memory registry, resume identity, inventory, Codex lifecycle, settle. Every moved step was audited for read/write independence. Stable-owner adoption and the adopted-claim publication set are unchanged. Also pins that an agent launch whose record cannot open takes its tab back and spawns nothing, and re-labels three TEMPORARY comments to their current owners. * fix(pty): preserve adopted claim return scheduling * fix(pty): keep shared commit reply types precise
…lects the moved tab as the window does (dark, layout-owner build only) (stablyai#31924) * fix(session-tabs): a tab main's groups lack keeps the place its writer listed it, so a headless phone lists a chat first (layout-owner build, L283) On a host with no window, a rebuild writes its rows under a group id main's layout lacks. The row writer's reorder treated every row of that group main does not hold (a chat, a browser page) as a stray and appended it to the active group, so a chat the user moved first came back last, in both the groups and the tab list. Strays now go after the id they follow in the writer's order (else first), the same rule a group main does hold already used; the window publication path shares it. * fix(session-tabs): a phone's split move and its create after a split tab go through main's layout on a windowless host (layout-owner build, L288, L289) On a host with no window, a phone's split move only rewrote the runtime's own rows, and its new terminal anchored after a split tab reached main's layout with no anchor. Every write of the rows takes main's groups and order, so the split collapsed back into one group and the new tab landed after the trailing tab. The split is now main's splitGroup command (the moved tab selected in its new group, as a desktop drop), and the create passes the anchor's tab to main's createTerminalTab, as a window's create does. An older phone sends no anchor and still gets the end. * test(session-tabs): type the split move's async reply in the dispatch stub, and read an optional group map (L289) * fix(session-tabs): a phone's split goes to main's layout only for a tab main holds, as the window sends it (layout-owner build, L289 review) With the Store's write notices, today's runtime-only split already reached main's groups through the session write; what it lost on a windowless host was the selection: the moved tab and its new group did not become the active ones, as they do after a window's drop. The split stays main's splitGroup for a tab main's groups hold, with the window's checks: a drop main's groups make a no-op sends nothing (the window's pane-column rule, now in shared), and a refusal is dropped silently. A row main does not hold (a chat or browser tab) splits as today, with no error. The create anchor and its layout-owner hand-off move to their own module. The surface test fixture's session writes now notify listeners, as the Store's do. * chore(session-tabs): log when main refuses a phone's split, as the window logs its own refusals * fix(session-tabs): a phone's terminal created after a chat or browser tab main holds lands after it, in its group (layout-owner build, L288 follow-up) Since browser and chat tabs went main-first, main's layout holds them, but a windowless create handed main the row id (agent-session:<id>), which is not main's tab id, so main put the new tab at the end of its first group. The anchor is now resolved to main's own tab, as a window's create names it; main's read of a workspace's layout is one method the tab-move path shares. * fix(session-tabs): one move path: main's tab move selects a split tab in its new group and skips the window's no-op split (layout-owner build, L289) A phone's split now goes only through main's tab move (stablyai#31812); this branch's own split routing is gone. For a split only, main's tab move now does what the window's drop does: it sends nothing for a drop that changes nothing (the window's pane-column check, reused), and after main applies the split it selects the moved tab and makes its new group active. Refusals keep that path's codes. * fix(session-tabs): resolve a create's anchor to main's tab inside the tab-move module, so only the old-client boundary's listed importers read old-client rows (L288 follow-up) * perf(session-tabs): read main's layout for a create's anchor only when main places it, so switch-off and appending phones skip that load * fix(session-tabs): restore the row-to-tab lookup the split selection and create anchor use, after stablyai#31925 dropped its import (layout-owner build, L288, L289) stablyai#31925 removed the L280 bridge in main's tab move, and with it the move's last use of resolveSessionTabRow, so it dropped the import; this branch's split selection and create-anchor lookup still resolve a row to main's tab through it. A row main's layout does not hold is now refused by main's move (tab_not_found) as stablyai#31925 rules; the phone test asserts that. * test(session-tabs): the L283 phone-order test opens its chat as the host does and uses a store that announces its writes (layout-owner build) Since stablyai#31925, main moves every tab of a workspace it owns and refuses a row its layout does not hold, and since D3b a chat the host opens is saved in main's layout. The test now opens the chat through the host's publish path and gives the runtime a profile-like store (partitions listed, writes announced), so the reorder reaches main's layout and its commit reaches the rows. * test(session-tabs): type the L283 test's profile-like store as the Store contract declares it * revert(session-tabs): drop the stray-placement change; main's layout holds chats and moves every row now (L283) Since D3b a chat the host opens is saved in main's layout, and since stablyai#31925 a phone cannot move a row main does not hold, so the rebuilt-group stray this placed no longer reaches a phone; the remaining strays are brief, and appending them gives the same order. withStrayIn and its callers return to main's behaviour, with its unit test. The phone-order spec stays as a guard that a windowless chat moved first stays first after a rebuild.
…fore it is sent (stablyai#30398) * fix(native-chat): attach a long paste as a text file, and say a message is too large before it is sent A paste of 32 KB or more (or one that would push the message past the 256 KB send limit) into a structured chat is saved as a file the agent reads, through the same pending-chip and @path route a dropped file takes: Orca's paste folder here, or the chat's attachment store on its paired server. Claude gets the paste folder as an allowed directory. A message still over the limit is handed back before it is sent, on desktop and the phone, with words naming the limit instead of the generic 'not sent, send it again'. * test: Claude launch parity snapshot grants the paste folder * fix(native-chat): a long paste replaces the selection at once and settles in place A long paste now puts an inline Pasted text pill where it went, replacing any selected text immediately, and the saved file (or inline text, or the original selection on failure) replaces that same pill when the save finishes, in its own chat's draft. Nothing reads the caret later, so order and position hold. The paste never joins the image row, so image numbers are unchanged. The size check measures the real message body with the selection replaced and images included. A server that keeps no files takes the paste inline when the message still fits. A pending paste a restart lost shows Paste not saved, and Send says so. * fix(native-chat): type the pasted-text parser and the composer's missing draft scope * fix(native-chat): admit paste references before goals and commands * fix(native-chat): resolve staged paste paths without editing the draft * fix(native-chat): consolidate paste imports for code quality checks * fix(native-chat): retain checked string types for saved paste paths * fix(native-chat): retain completed paste facts through history and delimit paths * fix(native-chat): keep structured question rendering within file limit * fix(native-chat): pasted or inserted text that looks like a paste token stays literal * fix(web): keep the browser's UI bridge under the file length limit * style: format the files stablyai#29982 merged unformatted * fix(native-chat): retain oversized drafts before send admission * fix(native-chat): keep the composer handle's merge resolution to main's destructure
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
1 task done
Author
|
Merged by the "Orca upstream sync" automation under SwapLabsInc/SwapLabs#223's rule, where CI no longer gates a sync.
|
This was referenced Oct 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ELI5
Upstream Orca moved forward 10 commits since this morning's sync (#38). This PR merges them into
swaplabs/main. They merge cleanly: none of them collides with a change the fork carries.What Changed
Upstream range
ec5eaf96c1..a45bd06eac, 10 commits (compare). The head is the fork's mirrormain, so the PR adds no fork commit; GitHub makes the merge commit.Upstream's 10 commits:
Why
Daily upstream sync.
Linked Issue
N/A: daily upstream sync.
Visual Proof
N/A: upstream code only. The fork changes no line here.
Testing
git merge-treeofa45bd06eacintoswaplabs/main(66ee345e87) is clean, with 0 conflicts.ec5eaf96c1are the 8 locale catalogs; each merged catalog parses with no duplicate key. No fork file references a module upstream moved or deleted in this range.pnpm tc, all four projects, "No type errors".orca-runtime-tests/worktree-ps-agent-row-dismissal.spec.tsruns insideorca-runtime.test.ts, which passes apart from one upstream test this host refuses to sign a fixture commit for (repository-project-operations-part-02.spec.ts).check-changed-code-quality.mjswithORCA_SYNC_PR_DIFF_BASE=a45bd06eac: 0 findings across 330 fork files.AI Disclosure
Prepared by the "Orca upstream sync" automation (Claude Code, Claude Opus 5.5).
Agent skill upstream boundary
Notes
orca-fork-ops statusforswaplabs/main(66ee345e87) against upstreama45bd06eac, before this merge:LOCAL: sync reviewcommit and LOCAL: build each macOS slice on its own architecture's runner #46's runner-arch commit);LOCAL:prefix and no upstream PR.No upstream release tags were missing from the fork.
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.