Skip to content

chore(sync): sincronizar feat/agent-hub-poc com main do upstream e regra no AGENTS.md - #1

Merged
richarddaros merged 690 commits into
feat/agent-hub-pocfrom
chore/sync-upstream-20261011
Oct 11, 2026
Merged

richarddaros merged 690 commits into
feat/agent-hub-pocfrom
chore/sync-upstream-20261011

Conversation

@richarddaros

Copy link
Copy Markdown
Owner

ELI5

O hub de agentes roda sobre o Orca original (stablyai/orca). Este PR traz para o feat/agent-hub-poc as 688 mudanças que o projeto original fez desde 06/10, com correções de bugs e funcionalidades novas. Também registra no AGENTS.md a regra de manter o hub sempre sincronizado.

What Changed

  • Main do fork: o main foi atualizado com gh repo sync e agora é igual ao do projeto original (ac529511b9).
  • Merge: origin/main entrou no feat/agent-hub-poc com --no-ff. Houve um único conflito, no .gitignore:
  • Nova seção "Fork Sync" no fim do AGENTS.md:
    • antes de trabalhar no hub, conferir a conta do gh e sincronizar o main do fork com o original;
    • sincronizar por uma branch chore/sync-upstream-<data> com PR, sem rebase, force-push nem git pull;
    • o main do fork não recebe commits próprios;
    • validar com install, tc e os testes do hub.

Depois do merge, git diff origin/main...feat/agent-hub-poc lista só os arquivos do hub: os scripts e docs do smoke, o README.md, o package.json, o .gitignore e o AGENTS.md.

Why

A regra deixa a sincronização explícita para qualquer agente que trabalhe no fork. O merge com PR preserva o histórico do hub e o do projeto original. Rebase reescreveria uma branch compartilhada.

Testing

Rodado no worktree da branch:

  • pnpm install --frozen-lockfile: ok;
  • pnpm tc: ok;
  • pnpm test:agent-hub: 6 de 6 testes.

Não rodei a suíte completa nem o build.

  • Revisão independente por agente de contexto limpo: aprovada depois de 2 ajustes no AGENTS.md.

Notes

  • Seu checkout local (feat/agent-hub-poc) tem mudanças sem commit (pnpm-lock.yaml e lefthook.yml) e está rodando o Orca em dev. Depois do merge, ele precisa de git merge --ff-only origin/feat/agent-hub-poc e pnpm install.
  • Hooks: os commits foram feitos sem o lint-staged do pre-commit, que rodaria lint nos ~10 mil arquivos que vieram do projeto original.

AmoabaKelvin and others added 30 commits October 9, 2026 23:33
…i#26276)

Spinners swap to a still hourglass instead of freezing; chevrons, the rail and popovers stop moving.
… serve (stablyai#27158)

* fix(pairing): advertise the key and a fallback port the host can actually serve

* test(runtime): use a consistent keypair fixture now that the advertised key is derived

* fix(pairing): keep dev's pinned 6769 out of other instances' fallback ladder

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
…server (stablyai#27165)

* fix(shell): OS open actions follow the file's owner, not the focused server

Every shell open request (openPath, openInFileManager, openInExternalEditor,
openFilePath, openFileUri) now carries the path's owning host. Main allows
only a local owner, plus the SSH editor launch when the owner is that same
SSH target, and no longer consults the focused server. The renderer reveal
and Open-in checks drop their focused-server check to match.

* test(e2e): name the owner on the local editor control open

* fix(explorer): Open in follows the catalog owner for folder and host-only SSH workspaces

The explorer toolbar and the source-control Open in menu took their SSH
connection from the repo row, which a folder workspace or a host-only SSH
repo does not have, so the route read as local. Both now derive the route
from the catalog-confirmed owner.

* fix(sidebar): Open in keeps the SSH target of folder and host-only SSH rows

The row resolver now returns the SSH connection it resolved alongside the
runtime owner, so a folder workspace or host-only SSH repo with no repo
connection no longer reads as local.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: ggbdpq <ggbdpq@gmail.com>
…i#27166)

Every add/re-pair path goes through the environment store; it now compares the
offer's public key with this profile's own runtime key before saving.

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: s546126 <s546126@users.noreply.github.com>
Co-authored-by: m4air <m4air@Mac.localdomain>
)

Co-authored-by: kazu-42 <91968271+kazu-42@users.noreply.github.com>
…st (stablyai#27177)

stablyai#27164 made an old host without a known non-Windows platform ask for an update
instead of answering its default list. The cross-version journey mocked the
capability probe but not the status read, so no request ever reached the wire.

Co-authored-by: m4air <m4air@Mac.localdomain>
Name Agent Dashboard columns using their translated visible headings.

Co-authored-by: Matheus Breguêz <matbrgz@gmail.com>
Use the approved Korean Finder wording and preserve it during locale regeneration.

Co-authored-by: YEONGUK LEE <contact@abruption.dev>
…force (stablyai#27172)

* fix(repos): deleting a project with live terminals warns and needs --force

orca project setup-delete now refuses a repo-backed project that still has
terminals not known to have exited or saved workspace details, unless --force.
The sidebar remove dialog says how many open terminals will close.

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

* fix(repos): count a sibling host's host-qualified workspace metadata in the delete guard

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

* test(sidebar): cover the remove dialog's open-terminal warning

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

* test(sidebar): type the dialog mock state without assertions

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

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: Claude <noreply@anthropic.com>
Preserve active graph lanes through unrelated root commits and share node/reference colors.

Isolate real-Git fixtures from inherited Git settings and use the existing public process-host import after the current-main package migration.

Co-authored-by: Matheus Breguêz <matbrgz@gmail.com>
* feat(hosts): servers publish a host descriptor

A paired server now reports a stable installation id, created once per
profile, plus an optional machine binding (HMAC keyed by that id over
the machine id and profile path) in status.get and in runtime pairing
offers. Optional fields only: older clients ignore them and older hosts
omit them. Clients start using it in the follow-up.

* fix(hosts): serialize installation id creation so concurrent starts never fork it

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
…7188)

* feat(ports): host-scoped port scan and stop on the server

Add workspacePorts.scanHost/killHost, addressed by workspace and resolved on the
server to the workspace's own execution host (this machine or one of its SSH
hosts). Stop is bound to the host its row was scanned on and is refused on SSH
hosts, where ownership cannot be proven. Advertised as
workspace-ports.host-scoped.v1.

* fix(ports): only this host's workspaces authorize Stop; a failed relay scan is not empty

Port ownership probes now come from host routing instead of the repo row's
connectionId, so an SSH repo that carries only executionHostId (or a runtime-
hosted repo) can no longer make a local listener look workspace-owned.

The relay's ports.detect now fails when it could not read the socket table
(unreadable /proc/net/tcp, or neither Windows scanner answering) instead of
answering an empty list, so a host scan reports unavailable rather than none.

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
…kground (stablyai#27022)

* Let a Grok chat list and stop the commands it left running in the background

A command Grok backgrounded (a dev server, a watcher, a monitor) showed only as a
transcript line: it never reached the background-tasks card above the composer, so
it could not be seen as running or stopped from Orca. Grok's subagents and Claude's
and Codex's background commands already list and stop there.

The ACP lane that publishes Grok's subagents as child records now also publishes
its background-task rows: a running task as a live background command or monitor,
an ended one as removed, derived from the rows the journal admitted. A Stop for one
of them goes through the same adapter route to Grok's own per-task kill
(x.ai/task/kill); Grok's completion notice ends the row, and a task Grok no longer
holds is removed at once. A refusal reports the task as not stopped; no answer or an
unreadable one leaves the outcome unknown.

Each Grok process is checked once at start with a no-target kill, beside the
existing subagent check. Only Grok naming the method unknown hides Stop.

* Settle a Grok task's transcript row when Stop finds it already gone

When Grok answered a Stop with already_exited or not_found, the card row was
removed out of band while the transcript row kept saying it was running, and a
later restated running notice could bring the card row back with Stop. The
answer now settles the transcript row through the translator, like the
subagent Stop, so the card row leaves because its row settled, the existing
no-relight rule keeps it gone, and a completion Grok still sends after
already_exited writes the real result. Also covers /clear being refused while
a Grok background command runs.
…26760)

* Keep repository detection off the main IPC thread

Share repository discovery decisions across synchronous compatibility callers and the existing asynchronous Git runner. Await discovery in project registration, nested imports, and folder upgrades, and recheck folder ownership after discovery completes.

* Make repository detection fixtures work on native Windows

* Await asynchronous Git checks in folder upgrade fixtures

* Prevent duplicate project registration after async discovery

* Check authoritative registration identity before renderer convergence

* Narrow repository responsiveness to detection and registration

* Keep one local project identity after concurrent registration

* Run registration SSH coverage in the existing Docker lane

* test(git): cover classifier failure stages and literal path identity

* test(git): use the current process host package

* test(repos): use current process host in registration fixture
* chore: remove verified unused Orca code

* chore: remove translations orphaned by dead code cleanup
…blyai#26790)

* Keep repository detection off the main IPC thread

Share repository discovery decisions across synchronous compatibility callers and the existing asynchronous Git runner. Await discovery in project registration, nested imports, and folder upgrades, and recheck folder ownership after discovery completes.

* Make repository detection fixtures work on native Windows

* Await asynchronous Git checks in folder upgrade fixtures

* Prevent duplicate project registration after async discovery

* Check authoritative registration identity before renderer convergence

* Narrow repository responsiveness to detection and registration

* Keep one local project identity after concurrent registration

* Run registration SSH coverage in the existing Docker lane

* Await Git discovery when scanning and importing nested projects

* test(git): cover classifier failure stages and literal path identity

* test(git): use the current process host package

* test(repos): use current process host in registration fixture
…ablyai#26791)

* Keep repository detection off the main IPC thread

Share repository discovery decisions across synchronous compatibility callers and the existing asynchronous Git runner. Await discovery in project registration, nested imports, and folder upgrades, and recheck folder ownership after discovery completes.

* Make repository detection fixtures work on native Windows

* Await asynchronous Git checks in folder upgrade fixtures

* Prevent duplicate project registration after async discovery

* Check authoritative registration identity before renderer convergence

* Narrow repository responsiveness to detection and registration

* Keep one local project identity after concurrent registration

* Run registration SSH coverage in the existing Docker lane

* Keep folder upgrades responsive and recheck pending project ownership

* test(git): cover classifier failure stages and literal path identity

* test(git): use the current process host package

* test(repos): use current process host in folder upgrade fixture

* test(repos): use current process host in registration fixture
…yai#26798)

* fix(codex): keep running subagent groups in long chats

* fix(codex): remember superseded settled child turns

* fix(native-chat): retain running Claude subagent groups
…lyai#27197)

* feat(pairing): re-pairing the same server keeps its environment

The web client minted a new environment id on every runtime-scope pairing link,
even for the same server key, so existing terminals kept the old id and failed
as ambiguous. A key-matched re-pair now keeps the id (bumping the pairing
revision) and pins the server's host descriptor; a same-key server with a
different installation gets a new id, and a downgraded server never replaces
the pin.

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

* fix(web): a reply from the replaced pairing never overwrites a same-server re-pair

Re-pairing now keeps the environment id, so fence on the pairing revision too:
a request captured before the re-pair can neither reopen a client with the
replaced token nor save the old pairing back over the new one.

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

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…blyai#27196)

* fix(mobile): agents for workspaces another runtime owns show why

The paired host no longer lists its own agents for a workspace another Orca
server owns: preflight.detectAgents refuses with workspace_on_other_runtime,
and the phone shows 'Agents on Another Server - Pair that server directly'.
The phone also recognises an unambiguous runtime-owned repo row itself, so an
older host is never asked.

* fix(mobile): a shared repo id with a runtime-owned row defers to a refusing host

Rows on several hosts can share a repo id, and the first row's SSH connection
could name the paired host's own target. When any row is runtime-owned the phone
now asks a host that advertises preflight.other-runtime-refusal.v1 to decide by
worktree, and shows the other-server row on an older host.

* fix(mobile): keep the agent-loader change inside the web bundle budget

Move the refusal code beside its capability in protocol-version, read the
capability in the loader, and test the runtime: prefix directly: importing
execution-host into the loader split a web bundle chunk (129 > 128 assets).

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
…tablyai#27198)

* [CI] Overlap independent process waits and remove two static tests

* [CI] Use the declared conditional Vitest chain
…ablyai#27174)

* refactor(wsl): move the WSL guest bundle sources out of src/relay

The WSL hook relay and WSL browser network relay are built from src/relay but are
not part of the SSH relay. Move them, and the 46 relay modules the hook relay
bundles, to src/wsl-guest so the SSH relay can be deleted on its own. Pure
renames; the built bundles are byte-identical.

Adds a boundary test so nothing outside src/relay imports it except relay tests.

* fix(ci): exempt renamed files' existing lint debt in the changed-lines gate

* test(relay): keep the cast suppression on the wrapped line

* test(relay): only parse files that mention relay in the import boundary check

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
* refactor(hosts): host authorities and owner resolution

Adds HostAuthority {endpoint, at} with authorityKey (existing host-id
spellings kept; nested 'SSH target behind server' gets an in-memory key no
host-id parser accepts), HostRoute {target, at}, and resolveOwner, a
focus-free owner resolver over the existing route resolvers. Today's
focus-reading answer is kept behind resolveOwnerWithLegacyFocus, which
counts every answer focus changed. No caller migrates in this PR.

* fix(hosts): resolveOwner keeps nested SSH places and strict active selection

The active workspace's host now resolves through the strict path, so rival
servers proxying one ssh:t stay ambiguous. A folder or repo row on a paired
server that names an SSH connection resolves to that nested target instead
of the server's own machine.

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
Repos, project groups, project host setups and folder workspaces fetched
from this app or a paired server were each stamped with their owner by a
separate function. They now go through adoptFromEndpoint, one adapter with
a per-kind arm. Behavior is unchanged; a characterization test was run
against the old stampers before they were deleted.

Co-authored-by: m4air <m4air@Mac.localdomain>
* fix(cli): check the runtime source before sending

A terminal Orca launches now carries which Orca launched it
(ORCA_RUNTIME_SOURCE_ID = the profile's installation id,
ORCA_RUNTIME_SOURCE_INCARNATION = the launching runtime id). Before a
request is sent, the CLI compares that with the runtime the profile's
runtime record names. Same runtime: sent as before. Different runtime:
a read-only status.get asks which profile it serves; the same profile (a
restart or update) is accepted, anything else is refused before the
request reaches it.

The vars cross into WSL through WSLENV. The SSH bridge stamps the
bridging runtime itself rather than trusting the remote env. The
existing orchestration compatibility stamp is untouched.

* fix(orcad): drop an inherited runtime source at startup

* fix(cli): an explicit switch to another profile is not fenced

The stamp also carries the launching runtime's userData path. A CLI that
dials a different profile than the one that launched its terminal, and
not the platform default an unpinned terminal falls back to, was pointed
there on purpose (orca-dev from a packaged Orca's terminal), so the
fence does not apply.

* refactor(cli): reuse the shared userData path comparison

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
…#27223)

Worktree change/activation events and the just-created worktree's owner now go
through adoptFromEndpoint, and a dev counter reports rows that reach a reader
unstamped but get attributed to a non-local host.

Co-authored-by: m4air <m4air@Mac.localdomain>
Jinwoo-H and others added 24 commits October 11, 2026 09:35
…an deploy it (stablyai#27462)

The staging director deploy binds its digest to staging-gce-c4's checked-in image. E is main
2bdb553 (stablyai#27405 event-loop max, stablyai#27406 sidecar), already mirrored to staging. C4 itself
changes only through its own reviewed refresh workflow.
…ce v2 is seen (stablyai#27473)

* fix(mobile): direct connections use v2 framing and never fall back once v2 is seen

* test: drop casts in direct v2 tests

* fix(mobile): count v2 handshake failures against the auth retry budget; latch only after host auth

* fix(mobile): pick direct framing at open, recheck the latch before legacy auth, and keep old hosts off the auth budget

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
…cell guard e2e (stablyai#27476)

Six feed cells, five in us-central1, so one dead US reserve cell is 1/6 of the fleet and 1/5 of its
region and the dead-cell guards in stablyai#27458 can decide. Staging only; nothing is applied by merging.
* feat(daemon): cap terminals per execution host

* fix(daemon): never let a ledger cleanup throw into a spawn

* fix(daemon): recreate the host terminal ledger dir after a /tmp cleaner

* test(daemon): drop a default-parameter case from the ledger dir test

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
…tablyai#27480)

* refactor(runtime): paired sockets authenticate to a device principal

* chore: format and comment touch-ups

* test(mobile): give the launch-authority socket fixture its principal

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
Fold the streaming dispatcher, the unary invocation helper and two
single-importer helpers into dispatcher.ts so request/response and
streaming-unary share one unary path. No behaviour change.

Co-authored-by: m4air <m4air@Mac.localdomain>
stablyai#27489)

* refactor(terminal): panes have two transports, local or remote runtime

* fix(terminal): keep local-only startup gates off unconverted SSH panes

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
…ai#27492)

* refactor(daemon): keep the gate's host share in its own module

* test(daemon): pin that an observing desktop's restores count against serve's budget

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
…ration (host) (stablyai#27493)

* feat(runtime): device-key authentication and per-installation key migration (host)

* fix(runtime): corrupt registry is never a revocation verdict; keyed sockets dispatch without a token; forks keep their Relay binding

* fix(runtime): keep an unparseable device registry aside; an unlisted key is never 'revoked' while it exists

* fix(runtime): a set-aside corrupt registry keeps verdicts doubtful even when the registry file is missing

* test(runtime): registerDeviceKey reaches the bound socket through the dispatcher for runtime and mobile rows

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
…graph; guard daemon externals at build (stablyai#27504)

Co-authored-by: m4air <m4air@Mac.localdomain>
… refuses (stablyai#27496)

* feat(daemon): keep the host's own record of refused legacy restores

* feat(daemon): the host keeps its own record of old-client restores it refuses

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
…blyai#27499)

* refactor(pty): delete the SSH PTY provider and its registry slot

Nothing in production registers an SSH PTY provider, so the registry's SSH
map was always empty: every SSH lookup answered undefined or threw the
'No PTY provider for connection' error. Delete the provider stack, its
consumer-session and source-recovery contracts, the registry maps and the
getSshProvider dependency, keeping each caller's existing result for an
absent provider. The registry now dispatches only 'local'; any other host
throws PtyHostNotDispatchableError, which keeps the renderer-matched
message for SSH ids and is never read as a gone or exited PTY.

* test(pty): keep the no-provider SSH routing cases in local-only form

* test: reword a comment naming the deleted SSH PTY provider

* test: drop an import the rebase left unused

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
…hemeral VM drop SSH provider arms (stablyai#27511)

* refactor(main): agent detection, automations, AI vault and ephemeral VM drop SSH provider arms

* refactor(skills): refuse SSH skill destinations at the branch and delete the relay skill services

* test(preflight): clear the local-detection mock before the SSH refusal cases

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
…secret (stablyai#27475)

* feat(mobile): verified https pairing links; custom scheme carries no secret

The desktop's copy-link now emits https://www.onorca.dev/pair#<code>, with the
code only in the fragment. Orca Mobile claims that link as a verified app link
and refuses any pairing code delivered through orca://, which any app can claim;
orca://pair alone opens the scanner with an explanation. In-app QR scan and
paste still accept the custom scheme, so older desktops and phones keep pairing.

The confirm screen shows the desktop address and host key fingerprint before
pairing. config/verified-links/ holds the apple-app-site-association,
assetlinks.json and fallback page to deploy on www.onorca.dev, with a test that
keeps them, mobile/app.config.js and the link builder in agreement.

Part of stablyai#17397.

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

* fix(mobile): refuse pairing codes nested in or normalized out of unverified links

The router unwraps expo-development-client ?url= links and normalizes dot
segments after +native-intent runs, so an orca:// wrapper could still deliver a
code to the confirm screen. Refuse any unverified link carrying code= at any
encoding depth, and match pairing routes on decoded, dot-free segments.

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

* fix(mobile): escape the apostrophe in the refused-link notice

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

* fix(mobile): decode escapes byte by byte before refusing nested pairing codes

An invalid UTF-8 escape made the whole escape run fail to decode, hiding an
adjacent encoded &code= that the router still decodes leniently.

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

* fix(mobile): decode nested pairing links to any depth before refusing codes

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

* fix(mobile): ignore URL-stripped whitespace when refusing nested pairing codes

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

* refactor(mobile): decide pairing-link refusal on the router's own parse

Stop re-implementing URL decoding. The guard now runs expo-router's own
extractExpoPathFromURL and parseUrlUsingCustomBase, the functions its linking
applies after +native-intent, and refuses any link from which the router would
read a `code` param or reach a pairing route with a payload. A link the router
cannot parse is refused. Release builds refuse expo-development-client
wrappers outright. A property-style test walks wrapping depths, encoding
layers, stripped control characters, case and unicode, and asserts that the
guard never passes on a link from which the router would read a code.

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

* fix(mobile): match pairing routes on the top-level segment only

A host link with a segment named pair was sent to the scanner.

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

* test(mobile): pin line-terminator fragment links as refused

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

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: Claude <noreply@anthropic.com>
…ading (stablyai#27515)

Nothing in production feeds the SSH PTY output intake: its only data and exit
entry points were called from tests, and the SSH PTY provider that would have
fed it is gone. Delete the intake, its source-obligation ledger, model
admission, projection publication and source-ack plumbing, and strip the
projection ids and source-credit bookkeeping they threaded through the local
renderer delivery path (accept, pending, flush, payload, accounting, exit,
session). Local terminal delivery is unchanged.

Because the intake also installed the runtime's remote source-range hooks,
this desktop host now answers a terminal.subscribe that asks for
ackOutputSourceRanges the way every orcad host already does: without the
capability, so the client uses the byte-window ACK. No source ranges were
ever attached to local output.

Co-authored-by: m4air <m4air@Mac.localdomain>
…irst frame before the agent starts (stablyai#27031)

* fix(native-chat): a new chat's effort pill keeps its first-frame value before the agent starts

A chat with no model pick runs the catalog's default model at that model's
default effort. The at-rest options answer now says so for every agent, not
only those whose live child reports the model's default, so the effort pill
no longer blanks and then jumps when the agent starts.

* fix(native-chat): read a chat's at-rest options for the folder it runs in

The at-rest options read asked the model catalog with no workspace, so it
always named the account's default model and effort, even in a repo whose
own agent config could pick another. The new chat's first frame, read for
that repo, names nothing there. The at-rest read now asks for the session's
own folder, so both frames agree on the model and the effort.

* fix(native-chat): scope the at-rest options read only for clients that take no model

A client that needs a model in every options answer (mobile today, older
desktops) refuses an answer naming none, and loses that read's commands with
it. Only a client advertising the optional-model capability gets the answer
for the chat's own folder; any other keeps today's account-default answer.

* test: run the at-rest workspace-scope RPC test in the Node SQLite project

* test: build catalog listings so the fixtures compile before and after main drops the tier map

* fix(native-chat): one at-rest rule — the chat's folder decides its default for every client

The folder-scoped catalog read now decides the default for every client. Where
it names one, the answer names that model and its effort. Where it names none,
a client that takes a model-less answer gets none, and one that needs a model
gets the account default model with no effort: exactly what it got before.

The reader is now required, and the first frame and the at-rest read share one
rule for which locations name a local folder.

* fix(native-chat): keep test callers of the host's options read untouched

Only in-process callers omit the reader at the host's entry, and they read
as the RPC gate treats an in-process caller. The shared read itself still
requires one. This leaves main's newer test call sites unconflicted.

* refactor: one native-local location check for Claude, Codex and the at-rest folder read
…tablyai#27205)

* fix(native-chat): a closed chat tab stays closed while the host is still closing it

Closing a chat tab removes it from the window at once. A tab-list frame the
host publishes before it has handled the close (a working chat's status
update, for one) still listed the chat, and the window appended it back at
the end of the strip until the host's own removal arrived.

The window now leaves out a chat whose close it has not heard back on, using
the in-flight close record it already keeps, and re-reads the host's tab list
once the close settles so a chat the host kept comes back.

* fix(native-chat): hide a closing chat tab through the existing close intent

Record a close intent for agent-session:<id> under the chat's host when a chat
tab close begins, so a host frame sent before the host handles the close cannot
re-add the chat at the end of the strip. The intent lifts when a host frame
stops listing the chat, or by its TTL. Only a failed host close clears it and
re-reads that worktree at the version already applied, so the chat the host
kept comes back.

Replaces the close-owner gate and the re-read after every close.

* fix(native-chat): end a chat close intent even when no host frame follows

Re-read the closed chat's worktree after every settled close, not only after a
failure, so a close the host had nothing new to publish for still ends its
intent; otherwise the same chat reopened within the intent's 20 s limit stayed
hidden. Skip the intent for floating-panel chats, whose frames are never
applied. Share one one-worktree local refresh with the Session History reopen
path. Reset close intents between tests in the reopened-tab e2e file, whose
harness tears the host down before a close's follow-up re-read lands.

* fix(native-chat): re-read after a successful chat close only for paired servers

This machine's host emits its removal frame before the close answers, and the
window applies it, so a local chat re-reads only when the close fails. A paired
server's frames travel apart from its answer, so, as for its terminal closes,
every close is followed by a read, and that read no longer joins a tab-list
request that began before the close. Floating-panel chats record no intent and
get no read.

* fix(native-chat): pin a chat close intent to the pairing the close began under

Record and clear the intent with one owner captured at close start, as paired
terminal closes do, so re-pairing a server mid-close cannot miss the clear, and
pass that pairing to the paired re-read.
Traz 688 commits de stablyai/orca main (ac52951). Único conflito no
.gitignore: o upstream removeu docs/reference/ e a lista de exceções;
ficaram só as exceções dos dois documentos do hub. Mudanças do hub
(smoke dos engines, docs, scripts no package.json) preservadas.

power-by: Richard Ros <1071678+richarddaros@users.noreply.github.com>
…pstream

Antes de trabalhar no feat/agent-hub-poc, o main do fork é atualizado
pelo gh repo sync e mergeado numa branch chore/sync-upstream-<data>,
com PR, sem rebase nem force-push. Registra também a validação do
sync e as exceções do .gitignore para os documentos do hub.

power-by: Richard Ros <1071678+richarddaros@users.noreply.github.com>
@richarddaros
richarddaros merged commit 171909c into feat/agent-hub-poc Oct 11, 2026
@richarddaros
richarddaros deleted the chore/sync-upstream-20261011 branch October 11, 2026 19:01
@richarddaros
richarddaros restored the chore/sync-upstream-20261011 branch October 11, 2026 19:01
@richarddaros
richarddaros deleted the chore/sync-upstream-20261011 branch October 11, 2026 19:01
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.