Repository navigation
Preserve full automation reports and sync the desktop release prerequisite - #37
Merged
Merged
Conversation
…before the first message (stablyai#28424)
…ing Recent (dark) (stablyai#30397) * fix(cleanup): count visits as last activity once terminals stop stamping Recent (dark) With ORCA_SIDEBAR_INPUTS=main, terminal start and exit no longer write lastActivityAt, so a workspace used only through plain shells could look idle to workspace cleanup and old in the jump palette. Both now read the later of the Recent stamp and the last visit. Switch off: unchanged. Co-Authored-By: Claude <noreply@anthropic.com> * fix(cleanup): stamp the workspace you leave; space table reads visits too (dark) Co-Authored-By: Claude <noreply@anthropic.com> * fix(cleanup): every reveal stamps the workspace you leave, host-aware (dark) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
…i#29903) * fix(terminal): a file dropped on a pane makes that pane active Dropping a file on an inactive pane's title strip pasted the path but left the other pane selected, because the drop only focused the terminal. Activate the pane instead (which also focuses it). Tracked in STA-9893. * test(e2e): give the title-strip drop the source owner real drags carry * test(e2e): preserve pane selection when checking title-strip drops --------- Co-authored-by: Orca Worker <orca-worker@localhost>
… or saved order (dark) (stablyai#30401) * refactor(sidebar): the stamp-sorted window list runs no settle, latch or saved order (dark) With ORCA_SIDEBAR_INPUTS=main the window's sort hook is a pure read of the rows' stamps: no settled-epoch store listener, no Smart latch, no saved Smart order writes, no class telemetry over the old attention map. Switch off: the existing hook, unchanged. Co-Authored-By: Claude <noreply@anthropic.com> * test(sidebar): stamp sort hook reads no live sources; stronger switch-on tests Co-Authored-By: Claude <noreply@anthropic.com> * test(sidebar): clear the order-save mock between tests Co-Authored-By: Claude <noreply@anthropic.com> * fix(sidebar): stamp sort reads a shared empty-sources constant, not a renderer layout literal The layout-writer ratchet counts layout field keys written in the renderer; the empty sources object now lives beside SmartSortSources in shared code. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
…s own (dark) (stablyai#30404) * refactor(sidebar): the stamp-sorted window list runs no settle, latch or saved order (dark) With ORCA_SIDEBAR_INPUTS=main the window's sort hook is a pure read of the rows' stamps: no settled-epoch store listener, no Smart latch, no saved Smart order writes, no class telemetry over the old attention map. Switch off: the existing hook, unchanged. Co-Authored-By: Claude <noreply@anthropic.com> * test(sidebar): stamp sort hook reads no live sources; stronger switch-on tests Co-Authored-By: Claude <noreply@anthropic.com> * test(sidebar): clear the order-save mock between tests Co-Authored-By: Claude <noreply@anthropic.com> * wip: main keeps sleeping retention only * fix(sidebar): stamp sort reads a shared empty-sources constant, not a renderer layout literal The layout-writer ratchet counts layout field keys written in the renderer; the empty sources object now lives beside SmartSortSources in shared code. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(sidebar): main keeps sleeping retention only; no order of its own (dark) Clients sort by the owning host's stamps, so main's temporal owner loses its settle window, Smart latch, create grace and catalog-listing classifier, and the shadow check stops comparing order. Retention, its clock and its shadow comparison stay. Co-Authored-By: Claude <noreply@anthropic.com> * fix(sidebar): every retention listing shares one sequence; publish after the first Co-Authored-By: Claude <noreply@anthropic.com> * test(sidebar): the first listing bumps the retention revision Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
…line skills (stablyai#30359) * refactor(native-chat): move the slash picker builder and upload chunking to shared Mobile builds the same skill and command list as desktop. * feat(mobile): redesign the chat composer with file attachments and inline skills * fix(mobile): the composer field owns its input style The page's font-size census cannot follow a style passed in as a prop.
…vals, name icon buttons (stablyai#30142)
…main has no pane for closes in the window (dark, layout-owner build only) (stablyai#30391) * fix(layout): a workspace only main held shows main's tab on the window's first visit (dark, layout-owner build only) * fix(layout): a live terminal no pane shows goes through main, which names the tab it holds; a pane close main has no pane for closes here (dark, layout-owner build only) * test: no type assertions in the CLI-first tests * refactor: the switch-off build keeps today's live-terminal mint as it was * review: frame sync under the line limit; the first-visit test names exactly main's tabs * fix(layout): adopt takes the recorded pane only while it is unbound * fix(layout): a refused live-terminal adoption is declined, not counted as shown
…ld orphans are reclaimed (stablyai#30148) * fix(macos): the TCC prompt watcher's log stream dies with Orca log stream only writes when its predicate matches (about never), so it never gets SIGPIPE when Orca dies without running stop() (crash, SIGKILL, e2e teardown, force-quit dev builds) and lived on under launchd. One dev machine had 126 orphans holding 566 MB and ~40% CPU. A /bin/sh wrapper now holds a never-written stdin pipe from Orca and kills log stream on EOF. * fix(macos): reclaim TCC log streams that older builds orphaned The wrapper stops new leaks, but users upgrading still have every log stream an earlier crash or force-quit left under launchd. Ten seconds after launch, once per process, Orca terminates launchd-parented processes running exactly the watcher's old command line. A live watcher's log stream is parented by its wrapper, so it never matches. * test(macos): document the fake log stream cast * fix(macos): arm log stream wrapper trap before fork; verify orphan executable * fix(macos): re-read orphan identity before SIGTERM; disable inherited errexit in wrapper
…30425) * feat(sidebar): Smart Done means finished and unread (dark) Owner decision Q1: with ORCA_SIDEBAR_INPUTS=main, a Done row holds its tier only while the workspace unread flag is set, so opening the workspace or sending the next prompt ends it. Reuses the existing flag; no new state or timer. Co-Authored-By: Claude <noreply@anthropic.com> * test(sidebar): reading a workspace drops its Done row in the live list Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
* Settle Codex review turns from their session completion * Preserve interruption relay metadata when settling Codex reviews * Keep the Codex turn id across status writers and settle through the existing host verdict path The turn id that matches a rollout turn end was dropped by every lead writer that did not pass it, so a failed turn after a child update never settled. Drop the synthetic Stop label: the unlabelled poll update already carries the host's main-agent verdict, including a failure, to current desktops. A remote desktop now takes the host's settled verdict for a late hook, and a rollout settle retires hook-only children like Stop does. * Retire Codex children through the poll and start a fresh turn on any non-compaction session start A rollout-settled turn deleted the child roster, so the local reconcile re-seeded the child from the last row as running and the pane stayed Working. Clear it instead, only from the poll (a child hook settling the root must not drop that live child), and let a remote desktop clear its roster when the host reports a done turn with no children. A resumed or forked session no longer inherits the previous turn id. Also drops accidental pnpm-lock churn. * Replay a Codex rollout turn end as the root Stop it stands in for Codex fires no Stop for internal subagents such as /review, so the rollout's task_complete was settling the main agent through a second path that every other status writer (local and remote reconcile, child hooks, polls) had to learn about. The transcript poll now replays that end as an ordinary root Stop through hook normalization, and a root hook for an already ended turn is classified as that Stop. A failed end carries its failure outcome and is published unlabelled like a cancellation, since desktops derive a labelled Stop's outcome as success. The separate settle path, the remote host-verdict adoption and the child-hook rollout reads are gone. * Keep an ended Codex turn retired across compaction, and keep WSL polls alive A compaction SessionStart queued before the next prompt carried the previous, already ended turn id, so the poll replayed its Stop: a Done flash and a second "finished" notification. A compaction now keeps the turn only while it is still running and its rollout end is unrecorded. The WSL guest rescheduled its transcript poll with the update instead of the stored row, so the poll stopped after its first update and a later turn end never replayed there. A Stop also clears the child roster instead of deleting it, so a reconcile cannot re-seed retired children from the previous row. * Restate an ended Codex turn's hook in provider dispatch Keeps the shared hook normalizer within its size limit after main's merge; the Codex dispatch returns the event it normalized, which the envelope uses for the published name and prompt classification. * Type the rollout record helper in the Codex turn-end test * Accept Codex's turn_complete name and keep only replayed Stops labelled The rollout reader also records turn_complete, the name the existing interruption reader already accepts. A poll row that is not a replay no longer restates the last hook's event name, so only a replayed Stop can carry the Stop label. * Drop a delayed Codex hook for an ended turn the lead has moved past A late root hook for an older finished turn was restated as Stop and marked the newer running turn Done; passing it through would instead rewind the lead's turn id so the poll replays the old end.
…he same list (dark) (stablyai#30426) * test(sidebar): the desktop window and a feed reader draw the same list (dark) * fix(sidebar): a feed reader lists a paired server's folders and nested workspaces as the window does (dark) * fix(sidebar): the paired-server shadow compares the lineage the server's check keeps (dark) * fix(sidebar): paired-server rows carry the unread flag Smart Done reads (dark)
…outs (stablyai#29587) * fix(shortcuts): Cmd+C no longer pastes on remapped Latin keyboard layouts On macOS the main-process paste intercept matched `code === 'KeyV'` OR `key === 'v'`, so on Turkish F (where the C letter sits on the physical KeyV) Cmd+C was routed to ui:appMenuPaste. Trust the produced key when it is a Latin letter or digit and only fall back to the physical code for non-Latin layouts (Cyrillic etc.), matching the shared keybinding matcher. Fixes stablyai#29574 Claude-Session: https://claude.ai/code/session_01TYbS9P1pnW4WRN7bGpuNaW * test(shortcuts): cover Dvorak, Korean and IME composition for the macOS paste intercept Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(shortcuts): match the macOS paste intercept by produced key token, in its own module The produced key token wins on every Latin layout, punctuation included (BEPO puts . on KeyV); non-Latin and IME keys fall back to the physical key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: İzzetEmre <emreizzet@hotmail.com> Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…s last active (dark) (stablyai#30431) * feat(cleanup): the owning host records last terminal use for cleanup's last active (dark) Owner decision Q2: with ORCA_SIDEBAR_INPUTS=main, the host that owns a workspace writes lastTerminalUseAt when a terminal takes input (window, phone or CLI, through the one input funnel) or a phone attaches, at most once a minute per workspace. Output never counts. Cleanup's last active reads it next to the Recent stamp, so a workspace used only from the phone never looks idle. Never a sort key. Co-Authored-By: Claude <noreply@anthropic.com> * fix(cleanup): count only typed input, skip paired-server terminals, share record routing --------- Co-authored-by: Claude <noreply@anthropic.com>
…ory (stablyai#29150) * fix(native-chat): identify the owner when resume create is refused * test(native-chat): consolidate transcript refusal cases * test(native-chat): keep ownership coverage at the launch boundary * test(native-chat): update adoption fixture for early ownership admission * test(native-chat): align resume admission assertions with host ownership * test(native-chat): keep RPC coverage focused on ownership proof * test(native-chat): assert blank request presence before optional source * fix(native-chat): admit the actual CLI source during chat creation * fix(native-chat): satisfy source admission lint checks * test(native-chat): provide the waiting hook prompt * test(native-chat): isolate source admission fixtures from host homes * test(native-chat): canonicalize adoption fixture directories * test(native-chat): preserve early ownership admission in source stack * Resume CLI conversations directly in native chat * fix(native-chat): preserve resume refusal behavior and honest transcript feedback * fix(native-chat): retain import read evidence in typed result * Use the header test fixture record type * Consolidate launch owner imports and correct feedback assertion * Keep existing resume translation in runtime catalog * fix(native-chat): preserve admitted source and prepared execution home * fix(chat): retain source evidence for dispatched adoption * fix(chat): keep source capture within module limits * Keep deferred chat publication in the shared launch owner * test(chat): allow host evidence in create routing * Satisfy launch publication checks and scope slot cleanup * Preserve canonical tab membership on projected reorders * Use recorded launch ownership for surface recovery * Reserve deferred chat order through existing group actions * Pass the active layout owner into launch cancellation * fix(native-chat): admit an unsaved transcript under a linked account folder A missing transcript stayed unresolved while its account root resolved through symlinks, so containment failed and a not-yet-saved conversation showed a load error instead of the unsaved notice. * refactor(native-chat): move the newest-item import window into its own module Keeps journal-legacy-import.ts under the line limit after the source identity observer landed on top of the streaming import. * fix(native-chat): restore the refusal error import lost in the main merge * test(native-chat): pass the layout owner in the layout-owner cancel test main's new test predates launch cancellation taking the active layout owner. * fix(native-chat): admit Pi transcripts against the root Session History walks A PI_CODING_AGENT_DIR that already ends in sessions, or any custom folder, made admission expect <dir>/sessions while the lookup searched <dir>, so a found conversation was refused. * refactor(native-chat): admit and look up CLI transcripts in one store per account Each agent's import described where an account keeps its conversations twice, once for the path check and once for the lookup, and the two could disagree (the linked-folder and Pi custom-root refusals). The import now names one conversation store per account; the create path resolves it once and both the hook-path check and the fallback lookup judge that same store. OpenCode's store is its exact database. * fix(native-chat): keep a History resume that joins a terminal resume alive when the terminal closes A History click that joins a pending terminal-tab resume now takes the launch over: the terminal hand-off runs at join time and the create resumes by conversation id, so closing the terminal before create no longer abandons the shared launch. * refactor(native-chat): move the launch source hand-off into its own module * fix: pick the chat that adopts a header resume the way History does
… list print (stablyai#30438) * Accept host aliases and infer the host for a single-setup project `orca worktree create --project scalp-it` failed with "Project is not set up on the selected host" even though the project has exactly one ready setup, and `--host trader-local` was rejected as an invalid value even though `orca host list` prints that name. Three separate causes: - `--project` was matched against the stored `projectId` only, which is a provider-scoped string (`github:owner/repo`). The display name shown by `orca project list` never matched, so the lookup found nothing and the failure was reported as a missing host. - With no `--host`, the host fallback existed but was unreachable, because the project lookup above had already filtered to zero candidates. - `parseExecutionHostId` accepts only `local`, `ssh:<id>` and `runtime:<id>`, so a bare alias could not parse at all. `ssh:<label>` already resolved labels; only the unprefixed spelling was missing. Now: - `--project` takes the project id or the display name, resolving through `project.list` and falling back to the setup's own display name for hosts that predate that method. Two projects sharing a name are refused rather than guessed. - `--host` is only required when the project is set up on more than one host. A single setup is used directly; an ambiguous one fails with every host and the flag to select it. - `--host <alias>` resolves against both axes: paired servers by name before routing, SSH targets by label once a client exists. An alias that names a machine on both is refused with the prefixed flag for each. Errors now echo the flag the caller typed instead of an `ssh:` spelling they did not use, and carry the hosts to retry with in `nextSteps`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Refuse a host alias that collides with duplicated SSH labels assertAliasNamesOneHost asked findSshTargetByName whether the alias also named an SSH target, but that function returns undefined for a label two targets share — deliberately, so an ambiguous label never resolves. Read as a boolean it says "no SSH target by that name", so an alias naming one paired server and two same-labelled SSH targets looked conflict-free and resolved to the server. The opposite direction was already covered: a unique SSH target against two servers sharing a name fails through assertEnvironmentNameUnambiguous. Fall back to ambiguousSshTargets so both axes refuse, and list every colliding target in nextSteps rather than only the first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Only fall back to setup display names on a server without project.list findProjectsByName caught every error from project.list and returned an empty list, so a network failure, a permission error, or a genuine server fault was indistinguishable from "no project by that name" — and the caller was then told `Project is not set up on the selected host` for a project that exists and is set up. Narrow the catch to method_not_found, the only code that means the weaker fallback is warranted, matching callProjectHostSetup and listSshTargets in the same layer. The function now returns null for that version gap and an empty array for a real miss, so the two cases stay distinguishable at the call site. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Refuse a legacy display-name match that spans two projects The pre-project.list fallback matches ProjectHostSetup.displayName, which is the repo's folder name rather than the project's name, so two projects holding repos with the same folder name both match. selectSetupOnHost would then have taken the first candidate — targeting a project the caller never named. Reject when the matched setups span more than one projectId and name each one, the same rule the project.list path already applies to duplicate display names. A single project with several setups is unaffected; the host selection below still decides between them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Spell the --host placeholder as <host> in the project setup usage lines The worktree create usage was updated to <host> when aliases became valid, but the four project setup-* lines kept <host-id> in both the command specs and the root help text they mirror. Those commands accept an alias too, so the narrower placeholder hid it from anyone reading help. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Document host names and the optional --host in the CLI docs The published CLI reference described `--host` as taking only `local`, `ssh:<target-id>` or `runtime:<environment-id>`, and the automations page showed `--host <hostId>` as required alongside `--project`. Both now understate what the commands accept, which is how the original report started: `orca host list` prints a name, the docs never said you could type it, so the generated id looked mandatory. Spell out that `--host` takes the bare name from `host list` on either axis, that a name resolves only when unique and is otherwise refused with the prefixed flag for each candidate, and that `--host` is unnecessary when the project has a single setup. Also note `--project` accepts the display name from `orca project list`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Name the runtime host id as the paired-server tie-breaker in the docs The host-selection page told readers to fall back to ids when a name is ambiguous but only ever showed `--environment <server-name>` for paired servers — and that selector is exactly the one that cannot separate two servers sharing a name. Spell out the pair the resolver actually emits in its nextSteps: `--host ssh:<target-id>` and `--host runtime:<environment-id>`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Spell the automations create usage as --project <id-or-name> [--host <host>] `automations create` resolves --project and --host through the same alias-capable resolver as `worktree create`, and its own notes already say --project takes a display name and --host takes a bare host name. The usage line still read `--project <id> [--host <id>]`, the last spot left on the old spelling (flagged by CodeRabbit after the main merge). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Give the fake runtime client cast in the host alias tests its SAFETY note Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): accept every name host list and project list print, everywhere --project/--host is taken Extends the alias work to the commands it did not reach and the names it missed: - `project setups --project <display name>` filtered by projectId only. - `project setup-existing-folder|setup-clone|setup-create --project <name>` now send the project id that name resolves to (pass-through for ids and for servers without project.list). - `--host "this machine"` (the local row's name) resolves to local, and is refused if an SSH target or paired server shares it. - One pair of wrapping quotes is ignored, since cmd.exe passes single quotes through literally. - With --environment/--pairing-code, a bare --host name is a machine the routed server reaches, not a different locally paired server. - An unknown project is reported as a project miss, not a host miss. Co-authored-by: Younghwan Chae <chyohw97@gmail.com> * fix(cli): keep exact project ids over names, and refuse an unverifiable host name An exact --project id whose only setup is not ready no longer falls through to a project whose display name equals that id. A bare --host name that matches a paired server now routes there only once this machine's SSH targets were actually read, and under --environment/--pairing-code a bare name always means a machine the routed server reaches. Co-authored-by: Younghwan Chae <chyohw97@gmail.com> --------- Co-authored-by: younghwan <chyohw97@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ayout.apply (stablyai#30430) Every renderer sender of layout.apply (sendLayoutApply, recordLayoutApply, the activation terminal create and the live terminal adoption) returns before the call for a worktree or folder workspace a paired server owns, and a source census pins that no other renderer file sends layout.apply.
…ring the last one sticks (stablyai#30433) A client's pane rename already lands in the host's saved layout (titlesByLeafId), but terminal.list/show never read it, and clearing a remote tab's last pane title sent no titles at all, which every host reads as 'unchanged'. - terminal summaries carry an optional paneTitle from the host's saved layout; the CLI list prints it ahead of the terminal title. Older hosts omit it. - clearing the last pane title of a remote tab pushes titlesByLeafId: {}, which old and new hosts both persist as cleared. Supersedes stablyai#30333, which renamed the whole tab via terminal.rename. Co-authored-by: wangshifeng <shifeng.wang@magic-shield.com>
…i#30379) * fix(drops): name extensionless dropped images by their bytes A file dropped onto a remote workspace with no extension (some drag sources hand images over as `noname`) now gets the extension its PNG/JPEG/GIF/WebP signature declares, so the agent sees `noname.png`. Repo icon detection reuses the same signature check. Fixes stablyai#30378 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(drops): sniff extensionless images only for .orca/drops and chat attachments Explorer imports into a user-picked remote folder keep the name, matching local imports. Chat attachments on a paired server now use the staged name so they get the extension too. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Neil <neil@stably.ai>
* Open file links beside their source tab's group Clicking a file link in a terminal or agent chat now opens the file in an editor next to that tab, not in whichever group happens to have focus. A new "Open in this group" row pins the file to the source group when that group has neighbors. - Capture the source tab at click time, so focus changes during path resolution don't redirect the file. - Rank candidate groups by adjacency: a neighbor already showing the file, then a neighbor showing an editor, then any neighbor, then the source group. - "Open in this group" never falls back to a browser, system app, or other group. If the group is gone or the target is not an editor, it shows a toast and does nothing. - Line reveals target the exact view that was opened, and are dropped if that view closes before the editor applies them. * rm scratch files * Preserve empty split panes during tab reconciliation Reconciliation removed every empty group, so an empty split pane the user had made beside a tab was collapsed on the next pass. A file link opened from that tab then landed in the source group instead of the empty pane. Reconciliation now removes only groups that stale-tab cleanup emptied, and keeps panes that were already empty. Tests cover terminal and agent-session sources in both worktree and folder workspaces. * Preserve runtime owner for local file links
…k, layout-owner build only) (stablyai#30439) * fix(layout): a CLI split whose pane main closes before it mounts answers at once (dark, layout-owner build only) * test(layout): the closed-before-mount split fails because of the close
…ght seams from their defining modules (stablyai#30440) The three ipc modules re-exported symbols owned elsewhere. Importers and test mocks now name the defining module, and the re-export lines are gone (no barrels).
…ting would stamp (stablyai#30445) A tab restored before its worktree catalog loads gets a placeholder row. SSH placeholders had no host, and a server's nested-SSH placeholder carried only runtime:E, so an ssh: host selection found no matching owner and routed the terminal as a direct dial from this desktop. Stamp the SSH target, and the server proxying it, from the repo row; leave a repo id that lives on several hosts unstamped.
…s the whole page and clicks land under the cursor (stablyai#30437) * fix(browser): a remote viewer larger than the host's browser pane sees the whole page and clicks land under the cursor Fixes stablyai#30341 * test: note why the screencast double is cast * fix(browser): drop guest frames until the fitted size is applied; forget the cached CSS size when the frame size changes * fix(browser): keep a press's release and markup inside the letterboxed remote frame * fix(browser): resume live frames once fitted metrics land; remeasure the page after its frame size changes
…its own host's copy (stablyai#30447) applyCreatedWorktree merged a create into any same-id row, so a local create could inherit a server twin's stamp (or wipe it). Lineage refresh stamped a server's reply with the focused host and replaced every same-id row, overwriting the local twin. Both now match id and host, and the lineage reply is stamped with the transport it came from.
… refuse a reserve roll target by name (stablyai#30707) * fix(relay-ops): let same-cap rolls run while another cell is reserve; refuse a reserve roll target by name The director refuses cell-status for a step-5 reserve cell with a 404 {error: cell_in_reserve_mode}. The same-cap headroom check read it for every general cell, so any roll failed while c7 was reserve. A reserve cell that is not being rolled now counts as no free slots (its seats are not in the database) and is listed with reserve: true. A reserve roll target, in the headroom check, the same-cap job's first cell-status read and the candidate tool, now fails with the design's procedure: flip it to admitMode=db first, roll, then flip it back. Any other 404 still fails. * fix(relay-ops): pin the headroom gate's imports as evidence code; name both cells in a two-cell reserve refusal
…d runtime-terminal-inspection (D2, D3) (stablyai#30684) * refactor: de-barrel remote-runtime-client and runtime-terminal-stream (D2) importers name the defining modules; the two vi.mock factories that named a re-export move to the defining module (pty-id spy) or drop the dead key (RemoteRuntimeClientError) * refactor(renderer): de-barrel runtime-terminal-inspection (D3) importers name runtime-terminal-input-recording, runtime-terminal-verified-input and shared/remote-runtime-pty-id; 22 vi.mock factories move the re-exported keys to those modules (pty-id keeps its other exports via importOriginal) * test: drop the duplicated verified-input mock (Opus P3)
…store (stablyai#30697) * plugins: extract the verified artifact-pack registry from language packs Pure refactor. Verify, bounded read, parse and per-plugin error handling move into PluginArtifactPackRegistry; language packs become one instance, so later data families reuse it instead of copying the file. * plugins: reconcile content families from one list Pure refactor. Reconcile and error reporting walk one family list in the same order as before, so a new family is one entry. * plugins: one line per family for declared artifacts and contribution defaults Pure refactor. Declared artifact paths are a list of per-family rows, and the contributes default comes from the schema (prefault) instead of a second copy of the field list; the existing defaults test pins the result. * plugins: extract the renderer plugin content list store Pure refactor. The fetch generation, startup join window and content-change subscription move into createPluginContentListStore; language packs become one instance, and store fields are renamed to entries/fetchEntries.
…uns out of space (stablyai#30679) * fix(ssh): say the host's disk is full when a managed-server install write fails for lack of space OpenSSH's sftp-server reports ENOSPC and EDQUOT as the generic SSH_FX_FAILURE, so a deploy onto a full home failed with the bare detail "Failure" under "Try connecting again". After a failed install write, probe the host's free space where the write was going; when it cannot hold the write, fail with an error that names the filesystem, how much is free and how much is needed. Lost or aborted transfers and Windows hosts keep their original error. Co-Authored-By: Claude <noreply@anthropic.com> * fix(ssh): diagnose only SFTP's generic failure on an exhausted filesystem Codex review: a partial upload may spend the room the rest needed, so compare against an empty filesystem, not the bundle size, and keep explicit refusals such as permission denied. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ssh): reuse formatKb and size an upload the way uploadDirectory walks it Opus review: the shared formatKb already exists, and following symlinks inside the tree could recurse; uploadDirectory follows the root and skips links below it. Co-Authored-By: Claude <noreply@anthropic.com> * test(ssh): measure the free-space probe in the host-op byte budget --------- Co-authored-by: Claude <noreply@anthropic.com>
…stablyai#30710) * fix(security): put every trust dialog on a host-owned token surface Plugin themes write CSS tokens on the document root, and dialogs portal to body, so any trust surface without plugin-security-chrome inherits them; a theme could hide what is being approved. The orca.yaml hook trust dialog, notebook run confirmation, plugin install, remove and rollback dialogs were missing it. DialogContent gains surface="security", which applies the host-owned tokens, and a scrollable prop for the plugin dialogs' existing viewport-height scrolling; every trust dialog uses the surface and a test lists them. The style guide says when to use each. * fix(security): keep inline trust decisions on the host-owned surface The agent command approval card (Allow/Deny) and the browser certificate override sit outside a dialog, so plugin theme tokens still reached them. A SecuritySurface primitive puts its child on the same host-owned token set as DialogContent surface="security"; both use it, and the security surface test now lists inline trust surfaces as well as dialogs.
…ablyai#30693) The Git runner sends a command into WSL when the working directory is a \wsl.localhost UNC path, even if no WSL distro is set in the options. literalPathspec only looked at the options, so Windows-style backslashes in file paths reached Git inside WSL unconverted and stage, unstage and discard failed to match the file. literalPathspec now also checks the worktree path, and every caller passes it. Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
…stablyai#30659) GitHub orgs using an SSH certificate authority get an SCP remote whose user is org-<id> rather than git. The three GitHub remote parsers only matched a literal git@ user, so those repos were classified not-github and lost PR, issue and check support. Co-authored-by: Yi-111-a <yi-111-a@users.noreply.github.com>
…er pages everywhere, headless sleep stops terminals (stablyai#30715) * fix(runtime): one owned-session teardown policy; removal closes host browser pages everywhere, headless sleep stops terminals A declared table says what each entry point (worktree, folder and project removal, sleep, disconnect) does to each owned kind (PTY, native chat, host browser page, launch record), so a new kind is a compile error until decided. Removal over desktop IPC and repo.rm now close the host's browser pages and launch records like the runtime removal; worktree.sleep with no renderer sleeps the host's terminals instead of doing nothing. Sleep->chat is declared pending stablyai#28445; disconnect stops nothing. * fix(runtime): project removal finds headless pages and failed launches without a client page; stub the new runtime method * fix(runtime): headless sleep rejects an unproven stop; read headless page owners through the bridge, not Electron
… remote contradicts (stablyai#30717) * fix(projects): refuse to set a folder up under a project its own GitHub remote contradicts Setting an existing folder up for a project stamped the project's identity as the folder's upstream even when the folder's own remote named another GitHub repository, so the folder was silently relabelled into the wrong project (fabricated upstream, wrong projectId on its setup and workspaces). Fixes stablyai#30663 * test: type the folder-remote spec store without casts * fix(projects): judge a registered folder by its current remotes; ignore host aliases * test: cover the desktop re-read of an already-registered folder
…the desktop (dark switch) (stablyai#30721) * fix(sidebar): key folder workspace rows by host in the shared builder so the phone matches the desktop Co-Authored-By: Claude <noreply@anthropic.com> * test(sidebar): pin the SSH folder row key encoding Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
…all an older version" (stablyai#30724) * fix(ssh): name a noexec home instead of calling the host unsupported * test(ssh): measure the stage exec probe in the host-op byte budget * fix(ssh): the connect error names a noexec home too * chore(i18n): add the noexec status line to the English catalog * fix(ssh): only the shell's exec refusal reads as noexec; other probe failures reach the self-test * fix(ssh): a stage the probe can't write skips the probe, so a full disk still reads as full * fix(ssh): read the probe's exit 126 as noexec in any locale
… of nothing (stablyai#30725) * fix(runtime): say why a new terminal on a host failed, with a retry * fix(runtime): never offer a retry or say refused when the host's reply was lost * fix(runtime): only a host error reply counts as refused; the wake flow keeps its own toast * refactor(runtime): one 'couldn't confirm' notice carrying the reason, no failure classification * fix(runtime): one create notice per workspace, so retried seeding can't stack toasts
… unproven ones (stablyai#30722) * refactor(pty): every PTY retirement names its exit proof; ratchet the unproven ones * refactor(pty): count raw ownership drops, route an abandoned relay stop to unverifiable, honest proof labels
This was referenced Oct 19, 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
Long Daily Sleep reports were saved as an 8,000-character preview while claiming they were complete. Automation history now preserves the bounded final report for the exact provider session and prompt, and reports truncation truthfully when only a preview is available.
What Changed
The execution host reuses Grok's completed-turn reader to carry at most 256 Ki characters separately from normal status. Capture verifies the provider session, prompt, terminal ownership and text prefix before saving the report. Normal status keeps its 8,000-character cap; SSH drops oversized optional prose before status, and replay cannot revive it. Completed runs read “Session completed.”
This branch also reconciles the upstream source required by the fork release policy, through
90e99c48f43. It preserves the fork's model settings, bound controls, pet voice, relay password and trusted-machine behavior. CI now uses hosted Ubuntu on this fork where upstream uses Blacksmith, with all required jobs and aggregate failure handling retained. Integration corrections cover draft admission, cancellation keys, native-cache preparation, runtime test routing and stale mocks/assertions. E2E artifact upload now finishes before later action startup rewrites the runner event payload, preventing a background-upload JSON parse race.The real WSL lane exposed a recovered-terminal close bug after host restart. Authenticated live daemon inventory now restores missing incarnation stop fences even before local adapter attachment, while preserving current-provider, host, live-session and no-overwrite checks. Follow-up integration fixes remove a duplicate automation persistence write, let unfinished quit records resume on reveal, notify the layout owner before returning retained completion evidence, and use the palette's ranked activity timestamp for its displayed age. Completed hibernation output still waits for an explicit wake.
Why
The reviewed 9,379-character report lost its final 1,379 characters. Separating final prose from normal status preserves the preview budget and uses established turn attribution. Session completion remains separate from the maintenance task's outcome. Existing identity fences, byte ceilings and quality limits are preserved.
Linked Issue
Owner-requested Daily Sleep repair. Work record:
projects/llm-wiki/work/2026-10-19-daily-sleep-pipeline-code-repair/plan.md. No upstream issue or PR.Visual Proof
N/A — no layout or styling changes. “Done” becomes “Session completed”; report fidelity and truncation are asserted against stored output. The failed E2E artifact confirms the current accessible New tab action is “Start a chat with Claude.”
Testing
91f1709(before the final cancellation-fixture-only correction): all typechecks pass (17,136 Node files, 15,056 renderer, 3,065 CLI, 31 auxiliary).fork-mainPR base. Full local lint and all repository ratchets/catalog checks pass, including the new unproven PTY retirement ratchet; five inherited documentation warnings remain.e42b811: 2,350 tests pass across 50 files, with three platform-specific skips. Complete real WSL workflow 39253587792 passed on that commit; forced-update close reportsptyKilled=trueand immediate censusliveSessions=0,inProcessSessions=0. This is historical evidence; the final head needs its own acceptance result.c201947b8a0: real WSL update acceptance 39257442065 passed. Downloaded receipts confirm forced-update closeptyKilled=true, immediate zero live/in-process census, both holders adoptedliveafter 60 seconds and later releasedexited, plus deferred/forced/silent/reboot updates.c201947b8a083e39c993a9f5378aa9918de2af4dpassed full PR Checks 39257442392: 42 successful jobs, nine skipped, no failures. Requiredverifyaggregate job 118088523513 passed; workflow path and head independently verified.AI Disclosure
Implemented with OpenAI Codex under the repository owner's instructions.
Review
Reviewed reuse, simplification, efficiency and boundary placement. Removed redundant persistence logic and kept wake policy in the existing eligibility module. No file-size suppression, timeout relaxation, byte-budget increase or incarnation-guard bypass.
Agent skill upstream boundary
Notes
Optional report data remains compatible with older peers. Transcript reads belong to the execution host. No wiki-content repair, historical journal cleanup or scheduler-outcome inference is included. Final head
c201947b8a0contains the upload race fix and cancellation fixture correction. Prior-head full run 39253587931 finished with 33 successful jobs, two underlying failures and the failed aggregate; both failures are corrected and locally tested. Release, installed-app long-report acceptance and work-item closure remain pending.Checklist