Skip to content

fix(native-chat): plain wording for chat errors and status rows - #24594

Merged
brennanb2025 merged 7 commits into
mainfrom
brennanb2025/chat-ui-plain-copy
Oct 3, 2026
Merged

brennanb2025 merged 7 commits into
mainfrom
brennanb2025/chat-ui-plain-copy

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 20 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​120 $\color{#cf222e}{\Huge{\mathbf{−}}}$​84 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​36
Prod 31 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​285 $\color{#cf222e}{\Huge{\mathbf{−}}}$​216 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​69

ELI5

When something goes wrong in the native chat, the message that explains it often used Orca's internal words: "2 journal lines could not be read", "[Orca: item truncated — 3145728 bytes exceeds the history page budget]", "The Orca running this chat has no record of it", a subagent marked "unverifiable · no contact", "Skills are unavailable for this host". Nobody reading the chat knows what a journal, a host, a page budget or "unverifiable" is, so these messages don't say what happened or what to do. Some were also wrong: "Update Orca" was offered for refusals that updating can't fix. Two errors above the composer were hard-coded English, and the two rows the host writes into a chat could never be translated.

This PR rewrites those messages in plain words that say what happened and, where there is one, what to do. It removes one line that only described Orca retrying in the background. It makes every one of these messages show in the reader's language.

What Changed

Before → after, as the user reads it:

Where it shows Before After
A chat action the computer running the chat doesn't recognise at all (that computer has an older Orca) The Orca running this chat doesn't support this. Update Orca, then try again. This needs a newer Orca on the computer running this chat. Update Orca there, then try again.
A chat action refused for a named reason that updating doesn't fix (the agent or location can't run there, chats are turned off there, or this app lacks a capability) Same sentence as above, including "Update Orca" This isn't available in this chat. (When the action was opening the chat's history: "This chat's history couldn't be loaded.")
A chat action refused because the previous agent might not have exited Orca hasn't confirmed that this chat's previous agent stopped. The previous agent in this chat may still be running.
A chat the computer running it has no record of The Orca running this chat has no record of it. Orca can't find this chat.
A send refused because an earlier message isn't settled A message you sent earlier hasn't been confirmed yet. A message you sent earlier isn't confirmed yet.
A write Orca couldn't save to the chat's history Orca couldn't record it in this chat's history. Orca couldn't save this to the chat's history.
Row shown while queued messages wait for the previous agent to exit Orca couldn't confirm Claude's previous process ended. Messages wait to be sent until Orca confirms it has ended. Claude from before may still be running. Your messages will send once it stops.
Row added after Orca repairs a damaged chat history 2 journal lines could not be read Part of this chat's history couldn't be loaded. (now translated)
Row replacing one history item too big to send [Orca: item truncated — N bytes exceeds the history page budget] This part of the chat was too large to show. (now translated)
Skills menu (/ picker) errors Skills are unavailable for this host (SSH chats only) / Could not load skills from this host Skills aren't available in SSH chats / Couldn't load skills. The screen-reader text now says the same sentence as the screen.
A subagent or background task Orca has lost sight of unverifiable · no contact / 2 unverifiable / 2 agents unverifiable · no contact no recent update / 2 with no recent update / 2 agents with no recent update
A chat whose history failed to load while Orca keeps retrying Could not load conversation + "The transcript could not be read. Orca keeps trying to load it." Could not load conversation (the retry line is gone; Orca still retries)
Above the composer, when Orca won't resend a message it couldn't confirm Message delivery is unconfirmed and Orca will not send it again (English only) Orca couldn't confirm your message reached the agent. Check the chat, then send it again if needed. (translated)
Above the composer, when the message couldn't be saved locally Message could not be saved to the outbox (English only) Couldn't save your message. Try again. (translated)

How it works:

  • Refusals. The sentences stay in the shared notice tables in src/shared/, which desktop translates and the phone shows in English. A refusal that names a reason now gets the new sentence notAvailable instead of the "update Orca" sentence (agent-session-refusal-notice.ts, the reason table). The "update Orca" sentence is kept only for a refusal with no reason. Every current host names a reason, so a refusal without one means the host didn't recognise the request (method_not_found), which proves it is older. For opening a chat's history, "This isn't available" would name nothing the reader asked for, so that case says the history couldn't be loaded.
  • The two rows the host writes. The repair row and the too-large row now carry a presentation value (history-repaired, history-item-too-large), the same field the "Context compacted" row already uses. The desktop words them with translate() (NativeChatNoticeRow.tsx). Their English text stays as written for older desktop builds and the phone. Both lost the row count or byte size they used to print, which meant nothing to the reader. Nothing parses these texts: the repair row is identified by its fixed item id. The copy and the presentation values live in the new src/shared/agent-session-host-status-rows.ts.
  • Composer errors. The send-outcome function in src/shared/structured-agent-session-send-disposition.ts used to return a hard-coded English sentence. It now returns sentence keys from the same table every other chat notice uses, and the desktop translates them with the existing agentSessionWriteNoticeText. The four places that report a failed local save use one shared pair of sentences instead of four copies of an English literal.
  • The retrying load error. The line under the title only described Orca's own background retry, so it is removed rather than reworded. The pane shows its title, or the specific headline when there is one, and never falls back to the terminal pane's "Toggle back to the terminal" line.
  • Lost-contact subagents and tasks. These now use the sidebar's existing words for this state, "no recent update", everywhere. After a count they read "2 with no recent update". The separate "no contact" reason only repeated the state, so it is gone. The internal state vocabulary (live / unverifiable / exited) is untouched.
  • The waiting row's promise is true. Every 5 minutes the idle sweep retries the stop it couldn't prove (structured-agent-session-idle-sweep.ts). A new message, an option change or a Stop also retries it. Whichever retry proves the old agent exited sends the waiting messages (releaseLease → wakeDelivery in structured-agent-session-host-lifetime.ts). structured-agent-session-claude-unproven-stop-send.test.ts covers the sweep-driven send. The row is written only while a message is queued.
  • Left to sibling PRs: the agent-starting refusal, the launch-failure toast, the loading pane, resume and restart toasts, the approval card, and the failed-send rows.

Why

These messages show up exactly when something has gone wrong, which is when the reader most needs to know what happened and what to do. Internal words help with neither. The new copy follows the common pattern for chat apps: short, says what happened ("Couldn't load skills", "This part of the chat was too large to show"), and gives a step only where one exists and would work ("Check the chat, then send it again if needed").

Rejected options:

  • Remove the repair and too-large rows. Each is the only sign that part of the conversation isn't shown. Removing them would hide that.
  • Keep the counts and byte sizes. They give the reader nothing to act on.
  • Keep English text in the host rows and composer errors. A sentence written on the host, or returned as a finished string from shared code, can't follow the reader's language. A typed value that each screen words is the same contract the compaction row and the refusal notices already use.
  • Keep the retry line and only reword it. It reports background work the reader can't act on, and the common pattern shows only that loading failed.

Wire compatibility: no new field, kind or opcode. presentation already exists as an open string that older readers ignore. A newer host talking to an older desktop build shows the two rows' English text, in normal text colour instead of muted grey. The phone always shows the English text. An older host keeps sending its old English rows, which a newer client shows as written. The too-large row is built on every history read, so it changes as soon as the host updates. The repair row is rewritten each time the chat is opened while the damage remains.

Differences from the common pattern:

  • Intended: a subagent or task Orca has lost sight of has its own state, "no recent update". The common pattern has no word for this: its group summary counts any unknown status as stopped. Orca keeps the state separate because losing contact with an agent, for example over SSH, must never be reported as the agent exiting.
  • Intended: the "update Orca" step depends on whether the refusal names a reason. The common pattern proves an older remote with a capability or version check before saying "update". Here the proof is that the host didn't recognise the request. One imperfect case remains: a host released between 2026-08-28 and 2026-09-28 named no reasons yet. If its real cause was a location it can't run (for example WSL), it gets the "update" sentence; after the update it gives the accurate "isn't available" sentence.
  • Intended: the host rows are a typed value with an English fallback, rather than text the client builds alone. This is so older clients and the phone, which have no wording for a new value, still show a sentence.
  • Intended: the "couldn't confirm your message reached the agent" error exists because Orca refuses to send a message twice when it can't tell whether the first send arrived. The common pattern has no such guard, so it has no such message. This PR only rewords it.
  • Temporary: an item too large for a history page is replaced whole by one row. The common pattern truncates inside the item and keeps the start visible. Follow-up: truncate in place.
  • Temporary: the waiting reason is a row in the transcript rather than a line on the queued message, and it stays in the transcript after the messages send. Follow-up: move it onto the queued message once the queued-messages capability ships.

Linked Issue

N/A (internal native-chat UI cleanup)

Visual Proof

Captured on Windows in two hidden, isolated test builds, with a stand-in agent in place of Claude. Before = base 306b4578aaa. After = this PR's final head 5ffbbc1c44d. These replace the earlier set, which was taken before the review fixes, on a Mac, at 13e47527fcb.

  • Damaged chat history. One saved history line was corrupted on purpose, then Orca was restarted. Before: "1 journal line could not be read". After: "Part of this chat's history couldn't be loaded." The red "Claude stopped while this response was in progress" row appears in both builds. It comes from the damaged line itself, not from this PR.
    repair-row-before
    repair-row-after
  • The same two rows with Orca set to Japanese (new since the earlier set). Before, both rows stay in English because the host writes them as finished text. After, both are translated: "このチャットの履歴の一部を読み込めませんでした。" and "チャットのこの部分は大きすぎるため表示できません。".
    repair-row-ja-before
    repair-row-ja-after
    too-large-row-ja-before
    too-large-row-ja-after
  • A subagent Orca lost sight of across a restart (new since the earlier set). Before: "Ran 1 subagent unverifiable". After: "Ran 1 subagent no recent update".
    lost-contact-before
    lost-contact-after
  • An answer too large to show, in English (a 2.6 MB reply). Kept from the earlier set, because the English text did not change after it. The final head was re-checked on Windows by reading the on-screen text: before "[Orca: item truncated — 2600434 bytes exceeds the history page budget]", after "This part of the chat was too large to show." A fresh English screenshot timed out.
    too-large-row-before.png
    too-large-row-after.png

The reworded rows keep the same look: 14 px muted grey in both builds, measured from the rendered page. The after build showed no new pop-up, toast, banner or status line.

Not captured:

  • Skills-menu errors. One needs an SSH chat. The other needs skill loading itself to fail, and the test build offered no way to force that.
  • The retrying load-error pane. Same reason: the test build offered no way to force the failure.
  • The composer's "Couldn't save your message". Filling the app's storage did not make a send fail.
  • The refusal notices, the waiting row and "couldn't confirm your message reached the agent". The stand-in agent can't produce these states on demand.

Each of these is covered by a rendered component test.

Testing

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

  • Updated every test that asserted the old copy, and added tests for the new behaviour:

    • a refusal with a named reason says "isn't available" for every action except opening history;
    • a refused history read on a host that can't run the chat says the history couldn't load;
    • the two host rows are worded through translation;
    • the skills-menu screen-reader text in SSH chats.
  • The targeted vitest files pass on the final head, including the mobile suites that use the shared refusal wording.

  • Localization catalog, extraction and coverage checks pass.

  • oxlint, the changed-code quality gate and React Doctor report no findings.

  • Web, node and CLI typechecks pass.

  • A trial merge in the planned order (main, then fix(native-chat): show "Sending…" on a message until the host confirms it #24606, then fix(native-chat): queued messages carry on in order after any turn, and nothing sends by itself after a restart #24586, then this PR) is clean at every step.

AI Disclosure

Review

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • SSH: the "newer Orca" sentence names "the computer running this chat", which is the remote machine for an SSH chat and this computer for a local one.
  • Phone: it shows the shared English sentences as written.
  • Merge with fix(native-chat): show "Sending…" on a message until the host confirms it #24606: this PR adds the sendOutcomeLost sentence. Its follow-up for the failed-send rows should reuse that sentence rather than add its own.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

Replaces Orca-internal words (host, journal, transcript, outbox, process,
unverifiable, "no contact", byte budgets) in native chat refusals, status
rows, the skills menu, subagent and background-task state labels and the
history-load error with plain language, and routes the two hard-coded
English composer errors through translate(). Copy only; no behaviour change.
…s words

- The held-message row says Orca keeps checking, which it does: the idle
  sweep retries the unproven stop and a landed retry sends what waited.
- An unsettled earlier message reads as unconfirmed, not undelivered.
- The skills-unavailable line names SSH chats, its only cause.
- Subagent and background-task rows say "no recent update", the sidebar's
  words for the same state, and "status unavailable" after a count; the
  row no longer repeats the state as a reason.
@brennanb2025
brennanb2025 marked this pull request as ready for review October 2, 2026 19:00
@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ea39c5f3-5975-4cc9-ba30-4149fef68a6d
📥 Commits

Reviewing files that changed from the base of the PR and between a5613b9 and 5ffbbc1.

📒 Files selected for processing (3)
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.read-error.test.tsx
  • src/shared/agent-session-refusal-notice.test.ts
  • src/shared/agent-session-refusal-notice.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The changes standardize journal-repair and oversized-history status rows, update structured-session send and save notices, and remove retry-status text from chat error states. Unverifiable background tasks now use “no recent update” labels and counted forms. Skill errors share text between visible status and screen-reader announcements. English and five other locales update related chat, history, skills, and task-status copy.

Priority: ➖ Normal

Merge Risk: 🔵 Low · up to 5ffbb

Some older mobile clients may be refused structured-chat features without being told that updating the client could help. The impact is limited to recovery guidance, so the change is mergeable with that issue in mind.

Architecture Summary

Architecture risk: 🔵 Low · up to 5ffbb

The change affects 2 systems.

Changed systems: src, mobile

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — src (service) was modified; 49 changed files map to changed impact.
  • observed — mobile (service) was modified; 1 changed file maps to changed impact.

Before / after behavior

  • observed — Modified behavior in mobile/src/session/mobile-structured-operation-id-retirement.test.ts: The expected failure message now specifies that the user should update Orca on the computer running the chat before trying again; the previous expectation used a generic unsupported-version message.
  • observed — Modified behavior in src/main/native-chat/agent-session-journal/journal-store-open.ts: The repair disclosure is now created without supplying input.malformedRows(); the existing malformed-row and read-only checks still govern whether it is appended.
  • observed — Modified behavior in src/main/native-chat/agent-session-journal/journal-store-schema.test.ts: Adds the journalRepairDisclosure import.
  • observed — Modified behavior in src/main/native-chat/agent-session-journal/journal-store-schema.test.ts: Defines REPAIR_TEXT from the disclosure body text for use in test expectations.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.81% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 31 functions across 44 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the native-chat wording changes and status rows, which are the main focus of the pull request.
Description check ✅ Passed The description is detailed and covers the change, rationale, testing, visual proof, compatibility, and checklist. It marks the linked issue as not applicable for an internal cleanup and leaves the AI…
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — read the full 42-file diff end to end; verified the type refactor, the copied/removed literals, and ran the changed test files (228 tests passing).

  • Plain-language copy — internal wording ("journal lines could not be read", "item truncated", "no contact", "unverifiable") rewritten across the shared notice/failure tables, the two host-written status rows, and the renderer fallbacks.
  • Typed send disposition — StructuredAgentSessionSendDisposition.error is now 'redeliveryRefused' | null instead of a free string; the renderer words it in the new structured-agent-session-outbox-error-text.ts, which also centralizes the four duplicated "couldn't save" literals.
  • State wording unified — unverifiable now reads "no recent update", with a new backgroundTaskStateCountWord giving "status unavailable" after a count; reasonUnverifiable and the row-count/byte-size parameters are removed.
  • i18n — en.json, en-runtime-required.json, and es/fr/ja/ko/zh updated for every changed or new key.

Verification notes: the disposition error change is internal (mobile has its own delivery path and never reads disposition.error), detail.kind === 'reason' is only ever waiting | blocked | unverifiable so the new backgroundTaskStateWord fallback fires only for unverifiable, no stale old literals remain repo-wide, and the exact repair/oversized literals stay pinned in journal-corruption-repair.test.ts and agent-session-history-page.test.ts.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

…eader's language

Both rows were finished English the host wrote into the chat, so nothing could
translate them. Each now names itself with a presentation, the way the
compaction row does, and the chat says it through translate(). The English text
stays on the row for clients that predate these presentations and for the phone.
…tences

The composer's two errors had their own wording file beside the sentence table
every other chat notice uses. The send outcome now carries notice parts, worded
by the same function as the rest. A refused redelivery says "Orca couldn't
confirm your message reached the agent. Check the chat, then send it again if
needed." (the same sentence the failed-send rework uses), and a message this
client couldn't store says "Couldn't save your message. Try again."
… and say only true causes

- The history error pane no longer adds "Orca keeps trying to load this chat."
  under its title: the read still retries on its own, but the pane says only
  that the chat didn't load.
- A write refused as unsupported asks for an Orca update only when no reason
  came back, which means the host is older. A named reason (a location or agent
  that can't run there, no chat host, a client missing the capability) now reads
  "This isn't available in this chat.", since updating doesn't fix it.
- A task Orca lost track of is "no recent update" everywhere; after a count it
  reads "2 agents with no recent update" instead of a second name.
- The skills menu announces the same sentence it shows, including in SSH chats.
- The row for messages held behind a previous agent reads "{{agent}} from before
  may still be running. Your messages will send once it stops."

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 310d6856-a74d-4ef0-bb80-57be1c8b15f7

📥 Commits

Reviewing files that changed from the base of the PR and between 15e4599 and a5613b9.

📒 Files selected for processing (40)
  • src/main/native-chat/agent-session-journal/journal-corruption-repair.test.ts
  • src/main/native-chat/agent-session-journal/journal-repair-disclosure.ts
  • src/main/native-chat/agent-session-wire/agent-session-history-page-bounds.ts
  • src/main/native-chat/agent-session-wire/agent-session-history-page-grouping-parity.test.ts
  • src/main/native-chat/agent-session-wire/agent-session-history-page.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-unproven-stop-send.test.ts
  • src/renderer/src/components/native-chat/NativeChatAutocompleteMenus.test.tsx
  • src/renderer/src/components/native-chat/NativeChatAutocompleteMenus.tsx
  • src/renderer/src/components/native-chat/NativeChatEmptyState.test.tsx
  • src/renderer/src/components/native-chat/NativeChatEmptyState.tsx
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.test.tsx
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.read-error.test.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.tsx
  • src/renderer/src/components/native-chat/NativeChatSubagentRun.test.tsx
  • src/renderer/src/components/native-chat/NativeChatSubagentRun.tsx
  • src/renderer/src/components/native-chat/agent-session-failure-words-text.test.ts
  • src/renderer/src/components/native-chat/agent-session-write-notice-text.ts
  • src/renderer/src/components/native-chat/background-task-header-content.ts
  • src/renderer/src/components/native-chat/background-task-roster.test.ts
  • src/renderer/src/components/native-chat/background-task-roster.ts
  • src/renderer/src/components/native-chat/structured-agent-session-outbox-dispatch.ts
  • src/renderer/src/components/native-chat/structured-agent-session-outbox-retry.ts
  • src/renderer/src/components/native-chat/structured-agent-session-read-failure-notice.ts
  • src/renderer/src/components/native-chat/use-structured-agent-session-outbox.test.tsx
  • src/renderer/src/components/native-chat/use-structured-agent-session-outbox.ts
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/shared/agent-session-failure-copy.ts
  • src/shared/agent-session-host-status-rows.ts
  • src/shared/agent-session-refusal-notice.test.ts
  • src/shared/agent-session-refusal-notice.ts
  • src/shared/agent-session-write-notice-copy.ts
  • src/shared/native-chat-empty-state.ts
  • src/shared/structured-agent-session-send-disposition.ts
💤 Files with no reviewable changes (1)
  • src/shared/native-chat-empty-state.ts
🚧 Files skipped from review as they are similar to previous changes (15)
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-unproven-stop-send.test.ts
  • src/shared/agent-session-failure-copy.ts
  • src/renderer/src/components/native-chat/NativeChatSubagentRun.tsx
  • src/renderer/src/components/native-chat/background-task-roster.test.ts
  • src/renderer/src/components/native-chat/structured-agent-session-outbox-dispatch.ts
  • src/renderer/src/components/native-chat/structured-agent-session-outbox-retry.ts
  • src/renderer/src/components/native-chat/use-structured-agent-session-outbox.ts
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/components/native-chat/use-structured-agent-session-outbox.test.tsx
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.

Comment on lines +209 to +216
// Thrown, so a client meets these only as an RPC error. The code's own words ask for an update,
// which only a method the host doesn't know proves; no reason here means an older Orca. An
// unsupported location or agent, or no chat host, is not fixed by updating, and a client missing
// the capability words this with its own older copy.
structured_agent_session_unsupported: {
clientCapabilityMissing: codeWords('updateOrca'),
hostDisabled: codeWords('hostFinding'),
hostUnsupported: codeWords('updateOrca')
clientCapabilityMissing: causeWords('notAvailable', 'hostFinding'),
hostDisabled: causeWords('notAvailable', 'hostFinding'),
hostUnsupported: causeWords('notAvailable', 'hostFinding')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

sed -n '185,250p' src/shared/agent-session-refusal-notice.ts
rg -n 'clientCapabilityMissing|hostUnsupported|notAvailable|hostFinding' src/shared/agent-session-refusal-notice* src/main/native-chat src/renderer/src/components/native-chat | head -100

Repository: stablyai/orca

Length of output: 6392


🏁 Script executed:

set -eu
printf '%s\n' '--- diff ---'
git diff --unified=30 306b4578aaa5c55f27add2a75607fd5eb347eca2  a5613b9e77eb017bda87cfaafed8c996d87dcd7a -- src/shared/agent-session-refusal-notice.ts src/shared/agent-session-refusal-notice.test.ts src/renderer/src/components/native-chat/agent-session-write-notice-text.ts
printf '%s\n' '--- notice definitions and rendering ---'
sed -n '1,115p' src/shared/agent-session-refusal-notice.ts
sed -n '230,330p' src/shared/agent-session-refusal-notice.ts
sed -n '1,115p' src/renderer/src/components/native-chat/agent-session-write-notice-text.ts
printf '%s\n' '--- clientCapabilityMissing references ---'
rg -n -C 8 'clientCapabilityMissing' src
printf '%s\n' '--- focused tests ---'
sed -n '280,375p' src/shared/agent-session-refusal-notice.test.ts
rg -n -C 12 'structured_agent_session_unsupported|hostDisabled|hostUnsupported|updateOrca|notAvailable' src/shared/agent-session-refusal-notice.test.ts src/main/native-chat

Repository: stablyai/orca

Length of output: 41576


🏁 Script executed:

printf '%s\n' 'pending-check'

Repository: stablyai/orca

Length of output: 165


🏁 Script executed:

set -eu
printf '%s\n' '--- diff ---'
git diff --unified=30 306b4578aaa5c55f27add2a75607fd5eb347eca2 a5613b9e77eb017bda87cfaafed8c996d87dcd7a -- src/shared/agent-session-refusal-notice.ts src/shared/agent-session-refusal-notice.test.ts src/renderer/src/components/native-chat/agent-session-write-notice-text.ts
printf '%s\n' '--- notice definitions and rendering ---'
sed -n '1,115p' src/shared/agent-session-refusal-notice.ts
sed -n '230,330p' src/shared/agent-session-refusal-notice.ts
sed -n '1,115p' src/renderer/src/components/native-chat/agent-session-write-notice-text.ts
printf '%s\n' '--- clientCapabilityMissing references ---'
rg -n -C 8 'clientCapabilityMissing' src
printf '%s\n' '--- focused tests ---'
sed -n '280,375p' src/shared/agent-session-refusal-notice.test.ts
rg -n -C 12 'structured_agent_session_unsupported|hostDisabled|hostUnsupported|updateOrca|notAvailable' src/shared/agent-session-refusal-notice.test.ts src/main/native-chat

Repository: stablyai/orca

Length of output: 41853


🏁 Script executed:

set -eu
printf '%s\n' '--- exact client capability references ---'
rg -n -C 15 'clientCapabilityMissing' src
printf '%s\n' '--- notice copy ---'
rg -n -C 8 'notAvailable|updateOrcaToKeepUsing|updateOrca' src/shared/agent-session-write-notice-copy.ts src/renderer/src/components/native-chat/agent-session-write-notice-text.ts
printf '%s\n' '--- notice flow ---'
sed -n '280,390p' src/shared/agent-session-refusal-notice.ts

Repository: stablyai/orca

Length of output: 20327


🏁 Script executed:

set -eu
printf '%s\n' '--- cause types and reason rendering ---'
sed -n '1,95p' src/shared/agent-session-refusal-notice.ts
sed -n '225,290p' src/shared/agent-session-refusal-notice.ts
printf '%s\n' '--- capability policy ---'
sed -n '1,180p' src/main/runtime/rpc/methods/structured-agent-session-policy.ts

Repository: stablyai/orca

Length of output: 8843


Keep update guidance for clientCapabilityMissing.

When requireStructuredCapability rejects a remote client that lacks STRUCTURED_AGENT_SESSION_RUNTIME_CAPABILITY, the refusal uses clientCapabilityMissing. The new mapping renders only “This isn't available in this chat.” This removes the update guidance for the older-client compatibility path. Restore the existing code-level mapping.

Suggested fix
-    clientCapabilityMissing: causeWords('notAvailable', 'hostFinding'),
+    clientCapabilityMissing: codeWords('updateOrca'),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Thrown, so a client meets these only as an RPC error. The code's own words ask for an update,
// which only a method the host doesn't know proves; no reason here means an older Orca. An
// unsupported location or agent, or no chat host, is not fixed by updating, and a client missing
// the capability words this with its own older copy.
structured_agent_session_unsupported: {
clientCapabilityMissing: codeWords('updateOrca'),
hostDisabled: codeWords('hostFinding'),
hostUnsupported: codeWords('updateOrca')
clientCapabilityMissing: causeWords('notAvailable', 'hostFinding'),
hostDisabled: causeWords('notAvailable', 'hostFinding'),
hostUnsupported: causeWords('notAvailable', 'hostFinding')
// Thrown, so a client meets these only as an RPC error. The code's own words ask for an update,
// which only a method the host doesn't know proves; no reason here means an older Orca. An
// unsupported location or agent, or no chat host, is not fixed by updating, and a client missing
// the capability words this with its own older copy.
structured_agent_session_unsupported: {
clientCapabilityMissing: codeWords('updateOrca'),
hostDisabled: causeWords('notAvailable', 'hostFinding'),
hostUnsupported: causeWords('notAvailable', 'hostFinding')

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — incremental re-review of the three commits since the prior pullfrog review (15e4599 → a5613b9), reading the delta and the full 51-file diff, then confirming with pnpm tc, the localization checks, and the changed test files (20 files, 279 tests passing).

  • Client-worded host status rows — the new agent-session-host-status-rows.ts gives the history-repair and oversized rows a typed presentation; the host still writes plain English into text, and NativeChatNoticeRow translates the row for the reader. presentation already existed on the journal item, so no wire field is added.
  • Composer send errors use the shared notice sentences — StructuredAgentSessionSendDisposition.error is now AgentSessionWriteNoticePart[]; the "couldn't save" and redelivery copy flow through agentSessionWriteNoticeText, and the obsolete structured-agent-session-outbox-error-text.ts is deleted.
  • structured_agent_session_unsupported reason copy — when the host names why, the notice now says "This isn't available in this chat." instead of asking to update Orca; the code's own update copy still stands for the no-reason (method-not-found) path.
  • Read-retry line dropped — headlineSaysUnread / NATIVE_CHAT_KEEPS_TRYING_COPY / agentSessionNoticeSaysThisChatUnread removed; a named read failure shows only its own sentence.
  • State wording — after a count, unverifiable reads "N with no recent update"; agentChildRowDetailText falls back to the state word; previousExitUnverifiable reworded.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

…n't load

A history read refused as unsupported with a named reason left the error pane
saying only "This isn't available in this chat.", which never said the chat
failed to load and named nothing the reader asked for. A read now says "This
chat's history couldn't be loaded."; other writes keep the shorter sentence.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — incremental re-review of the single commit since the prior pullfrog review (a5613b9 → 5ffbbc1), reading the delta against the full 51-file diff and running the two changed test files (2 files, 64 tests passing).

  • Read refusals for a host that can't run the chat now say the history didn't load — causeParts special-cases cause === 'notAvailable': a read-history write returns ['notDoneReadHistory'] ("This chat's history couldn't be loaded.") instead of "This isn't available in this chat.", while every other write keeps the shorter sentence. The pane showed the old line because the host's hostUnsupported/hostDisabled/clientCapabilityMissing reasons all map through notAvailable.
  • Reason-matrix tests split reads from other writes — the every-reason test now asserts ['notDoneReadHistory'] for structured_agent_session_unsupported reads and ['notAvailable'] otherwise, and the read-error pane gains a hostUnsupported case asserting the history sentence appears once and no "isn't available"/"newer Orca" text leaks.

The change is behaviorally narrow and the new pane test fails against the prior wording, so the fix has real coverage rather than an assertion that would pass either way.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review summary

The problem. When something went wrong in the native chat, the message that explained it often used Orca's internal words: "2 journal lines could not be read", "[Orca: item truncated — 3145728 bytes exceeds the history page budget]", a subagent marked "unverifiable · no contact", "Skills are unavailable for this host". A reader can't tell from these what happened or what to do. The first version of this PR reworded the English, but review found three deeper problems:

  • Wrong advice. The new "This needs a newer Orca… Update Orca there" sentence showed for refusals that updating can't fix. Examples: a chat whose location the host can't run (WSL, or Windows without the process check it needs), or chats turned off on that computer. A user would update and nothing would change.
  • Still English only. The two rows the host writes into a chat (history repaired, item too large) were still finished English sentences, so they could never follow the reader's language. The composer's error had also grown a second, separate way of wording errors beside the shared sentence table.
  • A line that shouldn't exist. "Orca keeps trying to load this chat." only describes Orca retrying in the background. The common pattern shows just that loading failed, so the line should go, not be reworded.

What changes for the user (final head 5ffbbc1c44d):

  • "Update Orca" appears only when the other computer didn't recognise the request at all, which proves it runs an older Orca. A refusal for a named reason says "This isn't available in this chat." If the history itself can't be opened, it says "This chat's history couldn't be loaded."
  • The repair row and the too-large row are now translated. An older desktop build, or the phone, shows the English text instead.
  • Both composer errors are translated: "Orca couldn't confirm your message reached the agent. Check the chat, then send it again if needed." and "Couldn't save your message. Try again."
  • A chat whose history failed to load shows only "Could not load conversation". The "keeps trying" line is gone, and Orca still retries.
  • A subagent or background task Orca has lost sight of has one name everywhere, "no recent update". After a count it reads "2 agents with no recent update".
  • The skills menu's screen-reader text matches what's on screen.
  • The row for messages waiting on the previous agent reads "Claude from before may still be running. Your messages will send once it stops."

Fixed during review:

  • P2:
    • "Update Orca" was shown for refusals it can't fix.
    • The host rows couldn't be translated.
    • The composer had a second wording path.
    • The retry line was reworded instead of removed.
  • P3:
    • One state had two names ("no recent update" and "status unavailable"). The second had no real precedent and is dropped.
    • The skills-menu screen-reader text didn't match the screen.
    • The waiting row named Orca's checking loop instead of what happens to the message.
    • A refused history read briefly said only "This isn't available in this chat." This was a side effect of two earlier review fixes, caught in round 2.
    • The PR description had several claims that turned out to be false. It now has correct ones and labels every difference from the common pattern as intended or temporary.

Deferred (all P3, none blocking):

  • A composer error stays in the old language if you switch languages while it's showing. Every other composer error behaves the same way, and before this PR it was always English.
  • The "messages waiting" row stays in the chat after the messages send. The common pattern shows no such row, so the right fix is to remove it, which is a behaviour change outside a wording PR.
  • The skills menu in SSH chats shows a heading plus "Skills aren't available in SSH chats". The common pattern has no such line.
  • An item too large to show is replaced whole rather than cut short inside, and a group of them gives several identical rows.
  • The "couldn't save" sentence pair lives in shared code but only the desktop uses it.
  • A host released between 2026-08-28 and 2026-09-28 doesn't say why it refuses, so it can still get the "update Orca" sentence. After updating, it gets the accurate one.

Verified:

  • Review: a full adversarial round with an architecture challenge, a second round on the fixes, a narrow check of the last fix, then a readiness check. No P0, P1 or P2 is open.

  • On the final head: the targeted test files, the phone's suites that share this wording, the translation checks, lint, the changed-code quality gate, and the web, node and CLI typechecks all pass. CI is green.

  • A trial merge in the planned order (main, then fix(native-chat): show "Sending…" on a message until the host confirms it #24606, then fix(native-chat): queued messages carry on in order after any turn, and nothing sends by itself after a restart #24586, then this PR) is clean at every step.

  • Hidden, isolated test builds on Windows, with a stand-in agent, before and after:

    • the repair row in English and Japanese;
    • the too-large row in Japanese, plus its English on-screen text;
    • the lost-contact subagent label.

    The reworded rows render at the same size and colour as before, and the new build showed no new pop-up, toast or banner. Screenshots are in the PR description.

Not verified:

@brennanb2025
brennanb2025 merged commit ac46d9e into main Oct 3, 2026
34 checks passed
AmethystLiang added a commit that referenced this pull request Oct 5, 2026
…use (#24271)

* fix(notebook): cancel kernel starts when the notebook closes (#24858)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(markdown): reduce Find memory for ordinary text (#24635)

* fix(markdown): avoid offset arrays for ASCII Find

* test(markdown): pin ASCII Find memory budget

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>

* fix(clipboard): decode uploaded images without joining all chunks (#24653)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(mobile): release file previews after their tabs close (#24655)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(editor): expire saved-file snapshots while the editor is idle (#24657)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>

* fix(ai-vault): bound transcript text before joining message blocks (#24659)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>

* fix(terminal): release retired status sources from the agent type cache (#24669)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(jira): expire cached attachment images while idle (#24678)

* fix(jira): expire cached attachment images while idle

* test(jira): preserve cache bounds and site expiry after clears

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>

* fix(mobile): merge terminal backlogs without rescanning growing strings (#24680)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>

* fix(terminal): release retired scrollback layouts from status routing (#24686)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(files): release expired mobile path inventories while idle (#24694)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(jira): discard detail replies after closing an issue (#24835)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(browser): avoid a redundant copy of live screencast images (#24851)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(terminal): release closed layouts while reveal frames are paused (#24721)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(quick-open): release expired legacy file inventories while idle (#24805)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(ssh): keep terminal buffers out of failed workspace sync status (#24833)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(native-chat): the desktop declares structured chat support to paired Orca servers (#24204)

* fix(native-chat): a host admits structured sessions by client capability, not its own chat setting

A host's experimentalStructuredNativeChat decided whether any paired client could reach
agentSession.* at all, and whether session.tabs.* showed it structured tabs. That setting is the
host user's own launch preference: whether a new agent opens as a chat or a terminal is decided by
whoever launches it. Using it as admission control meant a client whose own preference was
"structured chat" was refused on a host whose preference was "terminal", and chats opened while
the setting was on were withheld from mobile once it was turned off.

The gate now asks one thing: did the client advertise agent-session.structured.v1 (in-process
callers negotiate nothing and are always admitted). Tab projection and restore follow the same
rule. With the setting no longer gating anything, the separate cleanup gate (close, cancel,
unsubscribe, release), which existed only so those kept working after the setting was switched
off, is identical to the main gate and is folded into it. The settings listener that republished
tabs when the setting changed is removed, since projection no longer depends on it.

The host setting still picks the default for launches that start on the host itself
(agent.launch from mobile, orchestration worker-start).

* fix(native-chat): the desktop declares structured chat support to paired hosts

The desktop renderer advertised agent-session.structured.v1 (and the Claude, turn-item and
background-task capabilities that go with it) to its own main process but not to a paired Orca
server. The server therefore refused every agentSession.* call from the desktop and stripped
structured chat tabs out of the tab list it published to it, so a structured chat running on a
paired server never appeared on the desktop, even though the renderer already mirrors a host's
agent-session tabs and drives each one against the server that owns its workspace.

The same renderer reads structured chats on either host, so the remote Electron list now carries
the same structured-session capabilities as the local one, and the capability test pins that
nothing is advertised only locally.

* fix(native-chat): negotiate client-chosen launch mode so released phones and old servers keep terminals

Hosts advertise agent-session.structured.client-launch-mode.v1: they admit
structured sessions by client capability alone. A remote client that does
not advertise it (phones released before agent.launch) asks createSupport
to pick the launch mode, so the host keeps answering that with its own
setting, exactly as before. Cleanup methods keep their own named gate so a
future admission condition cannot make close or cancel refusable.

* refactor(runtime): keep the Electron client capability list in its own module

protocol-version.ts is at its line budget; the list is what the desktop
advertises to paired hosts, not the host's own contract.

* fix(native-chat): the desktop declares it picks each launch mode itself

Paired hosts and the desktop's own main process then answer createSupport
by the workspace rather than by their own chat setting.

* chore(native-chat): justify the two type assertions this change's lines touch

* fix(native-chat): chats that already exist keep showing whatever the chat setting says

The structured chat setting decides only what new agents open as. With it
off, this machine's structured chats used to be hidden while the host,
which no longer reads the setting, still reported them to the workspace
activation gate, so a workspace holding only a chat opened empty. The
local chat mirror and its startup restore now run whatever the setting
says, the continue-after-restart offer follows the chats that exist, and
the setting's copy says it applies to new agents.

* test(native-chat): pin that a host advertises the client-chosen launch mode

* fix(native-chat): mirror this machine's chats only where it holds them

Round 1 ran the local chat mirror for everyone so existing chats show
whatever the setting says. That gave every desktop a permanent
session-tabs listener, which turns on the runtime's phone replication
paths, plus two full session-tab censuses at startup, and made the
browser client mirror its remote host a second time.

The runtime now says whether it holds structured chats: its structured
host is built only when saved chats were restored at startup or a client
created one here, and it announces the moment one is built. The mirror,
the startup restore and the continue-after-restart offer run only when
the setting launches chats or the host holds some, and never in the
browser client. A chat a paired client creates here with the setting off
still appears at once. The chat behaviour settings show wherever chats
exist, and the setting's copy says it picks what new agents open as. The
toggle-off teardown this made dead is removed.

* test(native-chat): record install listeners without a cast

* fix(native-chat): mirror this machine's chats only once it holds one, not once its host is built

Session history, resume preparation, terminal resume commands and replay-safe phone launches all
build the structured host for users who never had a chat, which turned on the chat mirror and the
structured-only settings rows until the next restart. The signal is now derived from the host's
records (or a records file still owed its import) and pushed when the first chat is restored or
created. A throwing listener no longer fails the install that fired it.

* feat(native-chat): createSupport reports the saved selection a new chat on this host starts with

A chat on a paired server starts with the server's saved model and options, which the desktop could
not read, so its picker showed a guess. createSupport's answer, which the desktop already waits for
before a paired launch, now also carries that seed as a new optional field (older clients ignore it).
Create and createSupport read it through one resolver so they cannot drift.

* refactor(protocol): move the Electron remote client capability list into its own module

Merging main left protocol-version.ts one line over the max-lines limit on this branch. The list of
capabilities the desktop advertises to a paired host moves, unchanged, into
electron-remote-runtime-client-capabilities.ts, the module the next PR in the stack already uses
for it; importers point there.

* test(cross-version): stub the launch seed resolver createSupport now reads

* test(protocol): pin the desktop capability divergence against what a paired server receives

Every paired transport sends the shared remote base plus the Electron list, so the
divergence test now compares that union with the renderer's local list instead of
the declared Electron list. A capability added only to the shared base can no
longer slip past it. The two base-only capabilities it surfaced are recorded:
skills.install-result.v2 has no local caller; the authoritative-inventory label is
read by the local tabs sync but dropped by main, and is marked unsettled.

The turn-item and both background-task-stop capabilities were already sent through
the shared base, so the Electron list no longer repeats them. The wire set is
unchanged; this PR's real change on the wire is structured.v1, the Claude
structured capability and the client launch-mode capability.

* fix(native-chat): the desktop tells its own host it picks each launch mode, so retrying an existing chat works with the setting off

* docs(native-chat): name the real exit for the released-phone createSupport rule

* test(cross-version): a released client still gets the host-setting createSupport answer; a launch-mode client gets supported plus the seed

* fix(ai-vault): release expired host results while idle (#24766)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(orchestration): avoid loading task descriptions during promotion (#24781)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* feat(codex): run Windows Codex on the real ~/.codex (#24356)

Co-authored-by: Orca Worker <orca-worker@localhost>

* fix(mobile): release callbacks retained by canceled streams (#24625)

* fix(mobile): release callbacks retained by canceled streams

* test(mobile): cover delayed frames after stream cancellation

Preserve late-ready cleanup while rejecting canceled scrollback and terminal routing; cover unsent cancellation across browser, client events and session tabs.

* test(mobile): model unavailable queued stream transport

The encrypted sender rejects writes until connection setup completes. Keep existing session-tab unsubscribe attempts and assert canceled queued openers are never replayed.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: m4air <m4air@Mac.localdomain>

* fix(mobile): reduce base64 allocations for encrypted text frames (#24665)

* fix(mobile): reduce base64 allocations for encrypted text frames

* Correct screencast encoder comment after byte-codec extraction

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: m4air <m4air@Mac.localdomain>

* fix(cursor): resume exact conversation after startup status replay (#24670)

* fix(cursor): restore exact conversation after startup snapshot

* fix(terminal): preserve ready snapshot reattach and isolate bridge fixtures

* test(cursor): seed the real startup bridge after module resets

* test(terminal): settle startup snapshots in remote restore fixtures

Signed-off-by: Neil <neil@stably.ai>

---------

Signed-off-by: Neil <neil@stably.ai>

* fix(claude): inspect child tool IDs without rebuilding their output (#24707)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: m4air <m4air@Mac.localdomain>

* fix(native-chat): remove the "still starting" notice that flashed on chat launch (#24564)

* fix(native-chat): remove the "still starting" notice that flashed on chat launch

Every structured chat passes through a starting phase, and the pane showed
"<agent> is still starting. Messages wait until it is ready; close this chat to
give up on it." for it. A 5 s grace period only narrowed the flash to starts
that finish just past it. A message sent while the agent starts already counts
as working, so the chat's working indicator and Stop cover that state; the
notice only repeated it.

Removes the notice, its copy in every locale, the delayed-status hook that
existed only for it, and the per-child key the chat read only to reset it.

* docs(agents): no pop-up notices for transient or internal states

Records the rule the removed startup notice broke, so agents building UI
show transient states through existing surfaces instead of new messages.

* docs(agents): allow the common delayed loading placeholder

The rule against delaying a flashing message should not forbid a quiet
skeleton or spinner that waits a moment before appearing.

* fix(native-chat): stop publishing which provider child is starting

hostExecutionChild existed only to re-key the removed starting notice's delay.
Older clients read it as optional, so omitting it only changes when their
notice appears after a still-starting child is replaced.

* docs(agents): narrow the status-notice rule's wording

Ban 'execution host' rather than ordinary host copy, scope 'confirming' to a
connection, and keep the no-delay rule where the common pattern delays.

* docs(agents): let a control's own busy state wait, per the style guide

The status-notice rule covers notices and status lines; a delayed in-place
label swap like "Saving…" stays as STYLEGUIDE.md describes.

* docs(agents): keep the status-message guideline out of the repo

* fix(native-chat): no loading flash on open, one report for a failed start, no "Not reported" caption (#24588)

* fix(native-chat): stop the loading flash, the doubled launch failure, and the "Not reported" caption

- A structured chat no longer paints "Start a chat" or the full-pane
  "Loading conversation..." text before its first read settles; the pane
  stays blank until the history (or its absence) is known. A chat this
  view just started keeps its empty state through publish.
- A failed chat start is said once, by the chat's own Retry line. The
  "Could not open <agent> chat" toast that fired beside it, and again on
  every failed Retry, is removed; the raw error still goes to the log.
- The Fast mode switch in the options menu no longer carries a
  "Not reported" / "Default" caption.

* fix(native-chat): show a quiet spinner if a chat's first read lasts

The blank pane stayed blank with no cue for as long as the first read
took, including a slow remote read or a pending resume. The pane now
holds a textless spinner (announced as "Loading chat") that a CSS
animation delay keeps invisible for the first 250 ms, so a quick read
still paints nothing. A cancelled launch no longer holds the pane in
that state; it shows what the chat shows when not launching.

* test(native-chat): a refused new-tab chat start reports in its chat, not a toast

The new-tab launch opens (or reuses) the chat tab before the start can
fail, so its Retry line is the one report. The guard tests now pin that
the chat tab exists and no toast fires, for both a refused start and one
whose outcome could not be confirmed.

* fix(native-chat): leave a failed resume's pane blank beside its Retry line

A resumed chat whose start failed or could not be confirmed kept the
loading spinner turning forever above "Chat could not be started.", though
nothing was reading its history. The spinner now shows only while a read or
the resuming launch is in flight.

Also log a chat tab that throws while opening during worktree creation, and
drop a comment that still described the removed launch-failure toast.

* fix(native-chat): plain wording for chat errors and status rows (#24594)

* fix(native-chat): plain wording for chat errors and status rows

Replaces Orca-internal words (host, journal, transcript, outbox, process,
unverifiable, "no contact", byte budgets) in native chat refusals, status
rows, the skills menu, subagent and background-task state labels and the
history-load error with plain language, and routes the two hard-coded
English composer errors through translate(). Copy only; no behaviour change.

* fix(native-chat): match chat copy to what happens and to the sidebar's words

- The held-message row says Orca keeps checking, which it does: the idle
  sweep retries the unproven stop and a landed retry sends what waited.
- An unsettled earlier message reads as unconfirmed, not undelivered.
- The skills-unavailable line names SSH chats, its only cause.
- Subagent and background-task rows say "no recent update", the sidebar's
  words for the same state, and "status unavailable" after a count; the
  row no longer repeats the state as a reason.

* test(native-chat): find the repair row by its own text, not the old wording

* fix(native-chat): word the history-repair and too-large rows in the reader's language

Both rows were finished English the host wrote into the chat, so nothing could
translate them. Each now names itself with a presentation, the way the
compaction row does, and the chat says it through translate(). The English text
stays on the row for clients that predate these presentations and for the phone.

* fix(native-chat): say composer send errors with the chat's notice sentences

The composer's two errors had their own wording file beside the sentence table
every other chat notice uses. The send outcome now carries notice parts, worded
by the same function as the rest. A refused redelivery says "Orca couldn't
confirm your message reached the agent. Check the chat, then send it again if
needed." (the same sentence the failed-send rework uses), and a message this
client couldn't store says "Couldn't save your message. Try again."

* fix(native-chat): drop the retry line, keep one name for a lost task, and say only true causes

- The history error pane no longer adds "Orca keeps trying to load this chat."
  under its title: the read still retries on its own, but the pane says only
  that the chat didn't load.
- A write refused as unsupported asks for an Orca update only when no reason
  came back, which means the host is older. A named reason (a location or agent
  that can't run there, no chat host, a client missing the capability) now reads
  "This isn't available in this chat.", since updating doesn't fix it.
- A task Orca lost track of is "no recent update" everywhere; after a count it
  reads "2 agents with no recent update" instead of a second name.
- The skills menu announces the same sentence it shows, including in SSH chats.
- The row for messages held behind a previous agent reads "{{agent}} from before
  may still be running. Your messages will send once it stops."

* fix(native-chat): a chat whose host can't run it says its history didn't load

A history read refused as unsupported with a named reason left the error pane
saying only "This isn't available in this chat.", which never said the chat
failed to load and named nothing the reader asked for. A read now says "This
chat's history couldn't be loaded."; other writes keep the shorter sentence.

* Avoid repeated pnpm archive downloads in cache producers (#24927)

* Let measured cache producers keep stores without downloading them

* Check that restore-only callers do not publish a producer path

* Enable the measured producer mode and record hosted comparisons

* fix(usage): include OpenCode cached input in totals

Normalize OpenCode cache reads and writes consistently across usage views, persistence and telemetry.

Continues #20187.

Co-authored-by: griffinmartin <griffinmartin@users.noreply.github.com>

* fix(opencode): atomically install status plugin entrypoints

Retain complete status plugin files during replacement, symlinks and existing permissions, including legacy Windows directory permission recovery.

Fixes #24121. Continues #24131; permission-recovery review credited to pullfrog.

Co-authored-by: Ahmed Nagy <ahmednagy25t@gmail.com>

* fix(opencode): select tmux status on the execution host

Track the attested tmux selected pane in the canonical status store and fence retired refreshes after asynchronous root resolution.

Fixes #10039.

* feat(accounts): link standalone GLM Coding Plans (#24618)

* feat(accounts): link standalone GLM Coding Plans

Adapt the reviewed GLM accounts contribution to current main, retain Antigravity behavior, guard late credential results, expose storage protection, and redact quota errors.

Co-authored-by: Luchong <lu740528977@gmail.com>

* fix(accounts): retain GLM credential results during quota refresh

* fix(accounts): make GLM credential editing desktop-only

* fix(accounts): mirror the host GLM site in paired clients

* fix(accounts): report unknown GLM host details and split web settings tests

Apply the independently reviewed Accounts correction from697284a without the v2 adapter commits. Preserve the saved-key store and serialized write behavior.

* fix(zcode): ship required GLM account translation entries

* chore: record GLM reconciliation hook validation

* chore: validate installed GLM commit hooks

* test: complete GLM account fixtures and web API inventory

---------

Co-authored-by: Luchong <lu740528977@gmail.com>

* fix(ci): prevent concurrent pnpm refresh during mobile typechecks (#24776)

* fix(ci): run mobile typechecks without concurrent dependency refresh

* test(ci): check effective Linux E2E package list

* test(ci): preserve the mobile production compiler barrier

---------

Co-authored-by: Orca Integration Recovery <orca-validation@invalid.example>

* test(terminal): restore the live fish fixture prerequisites (#24947)

A restored pane waits for the initial status replay before subscribing to
PTY output. This fixture never settled that replay, so fish printed its
mode-2031 arm before the renderer connected. Its PTY API also omitted the
reset-input listener required by the serializer, aborting attachment.

Settle and dispose the existing startup-snapshot registration and provide
the same reset-listener mock used by the other PTY tests. The real fish
child-stdin assertions and timeouts remain unchanged. No production change.

* fix(shortcuts): defer TUI editing chords in terminal-first mode (#24640)

Restack the original focused change onto current main, preserving every owned source and test blob and the merged CI contract and journal cleanup fixes.

Original-commit: f707cde14ab8cb2670b4076916cdfb7e28c79983
fix(shortcuts): defer TUI editing chords in terminal-first mode

Original-commit: 0c6348e49e0d968e0170961d294a018adceaa9f3
docs(shortcuts): describe deferred preview terminal chords

Original-commit: be62c1b6c6b305cb8091161c1ccdd943a6e1d470
Align worktree history shortcut metadata with terminal conflict policy

Restacked-from: be62c1b6c6b305cb8091161c1ccdd943a6e1d470
Restacked-onto: f7b1f9d8be14d12244957ee0b710a3482ec62383

* Register supervised Qoder China and Qwen Code (#24616)

* Add Qoder session history and search with real CLI coverage

* Allow the real Qoder marker file to end with a newline

* Keep Qoder tool output out of history previews and search

* Keep Qoder search pages readable by older clients

* Verify persisted Qoder history after a real generated and resumed task

* Negotiate Qoder filters before searching an older execution host

* Combine search client imports for the CI plugin gate

* Keep the relay search oracle aligned with legacy agent filtering

* Register supervised Qoder China and Qwen lifecycle integration

* Cover Qoder China mobile assets and mixed-host resume gates

* Verify Qoder provider tags against the older released wire parser

* Verify China and Qwen keep independent Windows hook scripts

* Verify Qoder registrations against the installed older Windows release

* test(qoder): align search capability contracts and pin old-host fencing

* fix(qoder): rank exact picker identities and command aliases first

* test(qoder): preserve the regional CLI shared icon expectation

Keep the full bundled-asset and no-remote-image checks, with an explicit
shared-logo basename for Qoder China. The map also works with older
catalog type unions.

* fix(qoder): align China catalog entry with fallback order

---------

Co-authored-by: Orca Integration Recovery <orca-validation@invalid.example>

* Use the measured pnpm lookup policy automatically in hosted root CI (#24951)

* Select lookup automatically for the measured hosted root-install profile

* Record hosted automatic-mode cold cache publication proof

* Continue Antigravity IDE and 2.0 history in new CLI conversations (#24692)

* feat(antigravity): bridge IDE history into new CLI conversations

* fix(antigravity): preserve fresh-launch model and environment for IDE references

* fix(antigravity): forward IDE history opt-in through desktop IPC

* fix(antigravity): rebuild remote IDE reference startup on its host

* fix(antigravity): register IDE continuation action labels

* fix(antigravity): confine IDE references and bound metadata reads

* fix(antigravity): localize IDE continuation badges

* Preserve scanner service cache assertions and refresh Antigravity opening metadata

* Preserve Antigravity opening joins and target folder runtime authority

* fix(opencode): retry timed-out SSH plugin updates (#24666)

Preserve bounded retry behavior and the current-main status-envelope fields.

Original-PR: #24124
Reviewed-source: 103144f9c5029f9217f64970271a5b7f69d3f823

Co-authored-by: Justas Brazauskas <brazauskasjustas@gmail.com>

* fix(opencode): keep Go credentials private and resolve backend keys (#24615)

Preserve the complete credential storage, migration, IPC, Settings and rate-limit refresh change alongside standalone GLM plans, current-main database diagnostics and the reviewed unknown-backend environment correction. Keep native discovery cancellation third and selected environment fourth.

Original-topic-commit: 7903f1cddbc08fe1179f8bd964fff3dcb0e5d020
Original-topic-commit: 588117b5cf1dd57e2310c80068e3ddcc9f9044ec
Original-topic-commit: dedd4f8c862a961393977dc3c2547f049391b509
Original-topic-commit: 6645dae104ee5271139fcc0e9564d9223b74835d
Original-topic-commit: a25b80c02c1af7830b0e6a65e72d965b3ad98276
Restacked-from: a25b80c02c1af7830b0e6a65e72d965b3ad98276
Restacked-onto: b032867021c7ef1436ca606559e9d786580a84dc

Co-authored-by: kespineira <kespineira@users.noreply.github.com>
Co-authored-by: kevimux <kevimux@users.noreply.github.com>
Reported-by: pullfrog
Reviewed-full-source: 849fe093073f4c1606bd65d79a0c725d955d0d1f
Native-helper-source: 80dbe23237db191c1e6280001c7e0563f3ca8846


Reviewed-full-current-source: 36acb57d44adb3d378c0289c8c15f7da0fda214c

* Skip store notifications when refreshed work items are unchanged (#24530)

An identical forced refresh previously returned an empty Zustand patch, creating a new root state and notifying every subscriber. It now returns the current state after renewing the existing freshness timestamp. Real row or metadata changes still publish once.

* Read project activity once while sorting the sidebar (#24549)

Reuse the existing pure recent rank once per actual entry tuple within each synchronous sort; discard the lookup after sorting.

* Skip impossible link and tag matches in docs search results (#24646)

* Skip impossible HTML matches when formatting docs search results

After the existing link-removal phase, skip the unchanged HTML regex only when the current string has no closing delimiter.

* Skip impossible link and tag matches in docs search results

Skip the five unchanged link regexes when their protected-code input lacks ]; skip the unchanged HTML regex when its post-link input lacks >.

* Decode complete transcript lines without copying their bytes (#24546)

Decode each single owned Buffer synchronously; preserve concatenation for multipart records and remove a redundant tail array copy.

* Clear unused speech worker timers after errors and exit (#24924)

Call the existing idle timer cleanup when private current-worker state is cleared; keep current-worker guards, transcript/error order, deliberate warmth and stop deadline unchanged.

* Reuse documentation search excerpts during result navigation (#24574)

Memoize the existing pure excerpt renderer by complete raw text for the current result array, retaining original rendering as a miss fallback.

* Append subagent handoffs without recopying their message list (#24672)

Append each message reference to its private call-local scope list; retain the final merge and existing ordering.

* Cancel plugin retry timers when their fetch is replaced (#24700)

Reuse the existing timer clear block immediately after the fetch generation advances; preserve live retries and all state publications.

* Avoid rebuilding visible file paths for single-row selection (#24743)

Skip the visible path array only for keyboard replacement selection; the existing replacement branch never reads that order.

* Reuse prepared reads while searching saved agent conversations (#24535)

Use schema-complete session columns to enable the existing bounded statement cache without caching result rows.

* Reuse discovered mobile chunks during static traversal (#24774)

Iterate the existing live visited Set in FIFO discovery order instead of maintaining a second shifted queue; both actual callers own untouched esbuild JSON metadata.

* Skip unused image-size calculations in mobile web browser requests (#24941)

Use the existing mobile density budget only for mobile view; pass the existing constant to the existing assembler for web/default mode, where that argument is discarded. No cache, policy, request or native path changes.

* Skip diff analysis after a result has been discarded (#24711)

Move the unchanged pure render-limit calculation after both existing generation and section-token rejection fences.

* Skip late browser grab toasts after their surface closes (#24727)

Reuse the existing mounted-owner ref at the toast presentation entry while preserving all admitted extraction/screenshot and clipboard completion.

* Classify native chat waiting messages once (#24771)

Use the existing native filter traversal to populate a fresh waiting array, keeping the original predicate, policy, projection and output ordering while classifying each actual private slot once.

* Skip discarded Kanban pruning for an empty selection (#24782)

Guard only the existing open pruning branch when both its private selected Set and nullable anchor are empty; retain all original pre-guard projections and nonempty/anchor-only/public-helper behavior.

* Index discovered test files once during shard selection validation (#24532)

Verified selection plans previously validated each selected filename with a scan of all discovered files. One per-call Set now handles membership checks. Exact source/discovery checks, nonempty selection, fallback to all tests, shard balancing and manifests remain intact.

* Clear the watchdog benchmark heartbeat when CPU sampling fails (#24802)

Move the existing initial CPU observation and histogram enable inside the existing try/finally so their failures clear the sampler's owned heartbeat, preserving successful operation order and original errors.

* Reuse the parsed notification when leasing a push delivery (#24645)

* Reuse the parsed notification when leasing a push delivery

Pass the notification already parsed for the dismissal check into the existing private delivery builder.

* Reuse the parsed notification when leasing a push delivery

Pass the notification already parsed for the dismissal check into the existing private delivery builder.

* Update README downloads badge

* Let retired-cache GC observations settle across the existing six-turn budget (#24967)

* Collect test-selection evidence when full unit tests fail (#24955)

* Collect advisory unit-selection evidence from failed full runs

* Trigger checks after retargeting the evidence fix to main

* Check each project repository once while filtering mobile cards (#24540)

Reuse exact raw source/slug matching decisions within one project filter call, preserving the matcher, membership, negative matches, output order and identity.

* Skip renderer callbacks after their request has ended (#24631)

Reuse the existing pending-request identity check before starting its deferred renderer callback.

* Decode single-piece saved-session tails without copying them (#24632)

Decode the existing owned Buffer directly when the EOF tail has one piece; preserve the existing concatenation for multiple pieces.

* Avoid irrelevant scroll-action searches in Mac snapshots (#24731)

Check the current pure action name before searching for vertical scroll actions in the same immutable array.

* Stop copying every retained browser page before attachment (#24553)

Find the first page/generation match directly in the existing insertion-ordered Map instead of copying all page references into an array.

* Reuse event byte sizes when relay watchers notify several clients (#24558)

Store the existing grouped numeric byte-size array on the already call-local watcher batch sizing object, for reuse by later chunking clients.

* Stop building unused import candidates in the test planner (#24611)

Replace the existing ordered extension map/find with a loop that forms each candidate only when its existing lookup is reached.

* docs(terminal): explain local macOS/Linux shell startup files

Document the actual login/interactive shell startup-file order and existing shell setup behavior.

Co-authored-by: brynnclaw <261708852+brynnclaw@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>

* fix(editor): recognize Ruby task and configuration files

Add Ruby task/configuration filenames to the existing generated language associations.

Co-authored-by: ggbdpq <ggbdpq@gmail.com>
Co-authored-by: Neil <neil@stably.ai>

* Speed up large Markdown Find and render oversized tables (#24948)

* Speed up large Markdown Find and render oversized tables

* Poll table preview geometry outside hidden renderers

* Preserve Markdown navigation through refresh and tab restoration

* Confirm Markdown restoration when refreshed content is ready

* Trace table refresh positions and update Unicode search reference

* Recognize queued measurement scrolls before restoring Markdown anchors

* Rebuild Markdown Find ranges after renderer components change

* fix(source-control): generate clean OpenCode messages locally and over SSH (#24613)

* fix(source-control): generate clean OpenCode answers on local and SSH hosts

Restack the original focused change onto current main, preserving every owned source and test blob and the merged CI contract and journal cleanup fixes.

Original-commit: 64bb15e3f20799a21f108c849b0bdff83c692712
fix(source-control): generate clean OpenCode answers on local and SSH hosts

Use configured models and JSON answer/error events, preserve run-first arguments, and handle the precise v2 variant rejection. Hydrate SSH execution-host PATH through the existing bounded login environment resolver before direct spawning.

Credits: andy-murr (PR #5197 SSH environment intent) and coelho-doti (PR #13065 argument-order intent).

Original-commit: 1b60ec5d11132a5fed0695faea5de782a228a8e5
fix(source-control): retry inline OpenCode model and variant options

Original-commit: 98fdecc7a33ef1571dbf2854f309e4bfa1ec4300
Preserve OpenCode named errors without a data message

Restacked-from: 98fdecc7a33ef1571dbf2854f309e4bfa1ec4300
Restacked-onto: f7b1f9d8be14d12244957ee0b710a3482ec62383

* fix(ci): prevent concurrent pnpm refresh during mobile typechecks (#24776)

* fix(ci): run mobile typechecks without concurrent dependency refresh

* test(ci): check effective Linux E2E package list

* test(ci): preserve the mobile production compiler barrier

---------

Co-authored-by: Orca Integration Recovery <orca-validation@invalid.example>

* test(terminal): restore the live fish fixture prerequisites (#24947)

A restored pane waits for the initial status replay before subscribing to
PTY output. This fixture never settled that replay, so fish printed its
mode-2031 arm before the renderer connected. Its PTY API also omitted the
reset-input listener required by the serializer, aborting attachment.

Settle and dispose the existing startup-snapshot registration and provide
the same reset-listener mock used by the other PTY tests. The real fish
child-stdin assertions and timeouts remain unchanged. No production change.

* fix(shortcuts): defer TUI editing chords in terminal-first mode (#24640)

Restack the original focused change onto current main, preserving every owned source and test blob and the merged CI contract and journal cleanup fixes.

Original-commit: f707cde14ab8cb2670b4076916cdfb7e28c79983
fix(shortcuts): defer TUI editing chords in terminal-first mode

Original-commit: 0c6348e49e0d968e0170961d294a018adceaa9f3
docs(shortcuts): describe deferred preview terminal chords

Original-commit: be62c1b6c6b305cb8091161c1ccdd943a6e1d470
Align worktree history shortcut metadata with terminal conflict policy

Restacked-from: be62c1b6c6b305cb8091161c1ccdd943a6e1d470
Restacked-onto: f7b1f9d8be14d12244957ee0b710a3482ec62383

* Register supervised Qoder China and Qwen Code (#24616)

* Add Qoder session history and search with real CLI coverage

* Allow the real Qoder marker file to end with a newline

* Keep Qoder tool output out of history previews and search

* Keep Qoder search pages readable by older clients

* Verify persisted Qoder history after a real generated and resumed task

* Negotiate Qoder filters before searching an older execution host

* Combine search client imports for the CI plugin gate

* Keep the relay search oracle aligned with legacy agent filtering

* Register supervised Qoder China and Qwen lifecycle integration

* Cover Qoder China mobile assets and mixed-host resume gates

* Verify Qoder provider tags against the older released wire parser

* Verify China and Qwen keep independent Windows hook scripts

* Verify Qoder registrations against the installed older Windows release

* test(qoder): align search capability contracts and pin old-host fencing

* fix(qoder): rank exact picker identities and command aliases first

* test(qoder): preserve the regional CLI shared icon expectation

Keep the full bundled-asset and no-remote-image checks, with an explicit
shared-logo basename for Qoder China. The map also works with older
catalog type unions.

* fix(qoder): align China catalog entry with fallback order

---------

Co-authored-by: Orca Integration Recovery <orca-validation@invalid.example>

* Use the measured pnpm lookup policy automatically in hosted root CI (#24951)

* Select lookup automatically for the measured hosted root-install profile

* Record hosted automatic-mode cold cache publication proof

* fix: bound remote generation setup and honor OpenCode option terminators

Count execution-host profile resolution inside the existing request deadline, cancel its waiter promptly, and pass only the remaining time to the child. Shared bounded profile probes keep their existing cache lifetime; the SSH transport margin is unchanged.

Read OpenCode output format from active final-argv options before -- so literal prompt arguments cannot select the JSON finalizer.

Fresh exact-source controls reproduce nine failures before; 139 related checks pass after, including primary/fallback delays, deadline boundaries, cancellation, parser metadata, and SSH lanes. Node typecheck and strict changed-file lint pass.

* Continue Antigravity IDE and 2.0 history in new CLI conversations (#24692)

* feat(antigravity): bridge IDE history into new CLI conversations

* fix(antigravity): preserve fresh-launch model and environment for IDE references

* fix(antigravity): forward IDE history opt-in through desktop IPC

* fix(antigravity): rebuild remote IDE reference startup on its host

* fix(antigravity): register IDE continuation action labels

* fix(antigravity): confine IDE references and bound metadata reads

* fix(antigravity): localize IDE continuation badges

* Preserve scanner service cache assertions and refresh Antigravity opening metadata

* Preserve Antigravity opening joins and target folder runtime authority

* fix(opencode): retry timed-out SSH plugin updates (#24666)

Preserve bounded retry behavior and the current-main status-envelope fields.

Original-PR: #24124
Reviewed-source: 103144f9c5029f9217f64970271a5b7f69d3f823

Co-authored-by: Justas Brazauskas <brazauskasjustas@gmail.com>

* fix(opencode): keep Go credentials private and resolve backend keys (#24615)

Preserve the complete credential storage, migration, IPC, Settings and rate-limit refresh change alongside standalone GLM plans, current-main database diagnostics and the reviewed unknown-backend environment correction. Keep native discovery cancellation third and selected environment fourth.

Original-topic-commit: 7903f1cddbc08fe1179f8bd964fff3dcb0e5d020
Original-topic-commit: 588117b5cf1dd57e2310c80068e3ddcc9f9044ec
Original-topic-commit: dedd4f8c862a961393977dc3c2547f049391b509
Original-topic-commit: 6645dae104ee5271139fcc0e9564d9223b74835d
Original-topic-commit: a25b80c02c1af7830b0e6a65e72d965b3ad98276
Restacked-from: a25b80c02c1af7830b0e6a65e72d965b3ad98276
Restacked-onto: b032867021c7ef1436ca606559e9d786580a84dc

Co-authored-by: kespineira <kespineira@users.noreply.github.com>
Co-authored-by: kevimux <kevimux@users.noreply.github.com>
Reported-by: pullfrog
Reviewed-full-source: 849fe093073f4c1606bd65d79a0c725d955d0d1f
Native-helper-source: 80dbe23237db191c1e6280001c7e0563f3ca8846


Reviewed-full-current-source: 36acb57d44adb3d378c0289c8c15f7da0fda214c

* fix(opencode): enforce deadline through executable startup

Keep synchronous Windows PATH resolution and child startup within the existing request budget.

---------

Co-authored-by: Orca Integration Recovery <orca-validation@invalid.example>
Co-authored-by: Justas Brazauskas <brazauskasjustas@gmail.com>

* fix(persistence): preserve projectGroupOrder on restart for flat folder-scan groups

Retain saved project ranks when the project remains in its folder-scan group.

Co-authored-by: lurunzi <lurunzi@gmail.com>
Co-authored-by: Neil <neil@stably.ai>

* fix(runtime): reclaim temp files orphaned by interrupted mobile store writes

Reuse the existing stale temporary-file cleanup policy when each mobile store opens.

Co-authored-by: LDH1103 <ldh517525@gmail.com>
Co-authored-by: Neil <neil@stably.ai>

* fix(terminal): show actionable copy for missing folder workspace paths

Show the existing folder-path failure with concrete recovery instructions.

Co-authored-by: Wayn_Liu <wayntingliu@gmail.com>
Co-authored-by: Neil <neil@stably.ai>

* docs: reference local orca.yaml and .worktreeinclude

Document the existing workspace configuration, include/copy rules and sharing behavior.

Co-authored-by: Neil <neil@stably.ai>

* fix(orchestration): allow model selection for OMP workers

Pass an explicitly requested model through the existing OMP worker launch catalog.

Co-authored-by: Neil <neil@stably.ai>

* fix(cli): preserve primitive success results in JSON output

Check for an object before inspecting screenshot fields so primitive success results remain printable.

Related: https://github.com/stablyai/orca/pull/14735

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: VXNCXNX <VXNCXNX@users.noreply.github.com>

* Show loaded file changes before deleting a workspace

Expose up to ten already loaded changed paths without altering deletion counts, hydration or authorization.

Related: https://github.com/stablyai/orca/pull/22778

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Michiel de Gooijer <mdgooijer@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(keybindings): record and match Option+digit shortcuts on macOS

Use the physical digit key for explicitly assigned Mac Option+digit shortcuts while retaining modifier checks.

Co-authored-by: marcuslannister <marcus@lannister.cc>
Co-authored-by: Neil <neil@stably.ai>

* fix(editor): don't throw closing a stale active file

Recover stale active-file selection within the owning workspace before choosing a surviving editor.

Related: https://github.com/stablyai/orca/pull/24715

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
Co-authored-by: Neil <neil@stably.ai>

* Fix Project Settings targeting for multiple local checkouts

Carry the selected checkout identity into the existing project Settings action.

Co-authored-by: fsmeier <1506919+fsmeier@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Neil <neil@stably.ai>

* feat(documents): open CSV and TSV files from the OS

Extend existing OS document associations and delivery to CSV/TSV, preserving restoration and authorization.

Co-authored-by: Neil <neil@stably.ai>

* feat(cli): link GitHub and GitLab items on worktree create and set

Expose and validate the existing workspace link fields, preserving omitted values and provider identity checks.

Related: https://github.com/stablyai/orca/pull/22609

Co-authored-by: marco song <marco.song@mvlchain.io>
Co-authored-by: SongMarco <20613630+SongMarco@users.noreply.github.com>
Co-authored-by: Luca Critelli <lucacri@gmail.com>
Co-authored-by: Neil <neil@stably.ai>

* feat(sidebar): include folder workspaces in keyboard navigation

Use the rendered sidebar row order and host identity when cycling through folder and Git workspaces.

Related: https://github.com/stablyai/orca/pull/10555

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: JeongUk Park <jeongph.dev@gmail.com>

* fix(build): turn off MSBuild file tracking for Windows native rebuilds

Default Windows native rebuilds to TrackFileAccess=false while preserving explicit caller preferences.

Co-authored-by: B1nh M1nh <43268322+b1nhm1nh@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Neil <neil@stably.ai>

* Fix Ctrl+M in Linux and Windows terminals

Keep the Minimize menu item but disable its accelerator registration on Linux and Windows.

Co-authored-by: Zhichang Yu <yuzhichang@gmail.com>
Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Ahmed Nagy <ahmednagy25t@gmail.com>

Related contribution: https://github.com/stablyai/orca/pull/24143

* fix(startup): read a nushell login PATH from $env.PATH

Use Nushell login command syntax and preserve the actual login PATH value.

Related: https://github.com/stablyai/orca/pull/22677

Co-authored-by: Kh05ifr4nD <meandSSH0219@gmail.com>
Co-authored-by: Neil <neil@stably.ai>

* fix(cursor): run local hooks through sh for non-POSIX login shells

Keep POSIX hook syntax inside one quoted sh command so the login shell can invoke it safely.

Related: https://github.com/stablyai/orca/pull/22663

Co-authored-by: Kh05ifr4nD <meandSSH0219@gmail.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Neil <neil@stably.ai>

* Fix word wrap for both panes in side-by-side diffs

Forward wrapping to both diff panes through the existing editor option path and clean up listeners.

Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Neil <neil@stably.ai>

* fix(monaco): highlight Svelte block closers inside markup

Return Svelte block closers to the existing markup tokenizer state.

Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Neil <neil@stably.ai>

* fix(repos): keep active clone dialog open on outside clicks

Ignore accidental outside dismissal only while cloning; Escape, Close and Back still cancel.

Related: https://github.com/stablyai/orca/pull/24581, https://github.com/stablyai/orca/pull/23430

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Nawapat Buakoet <nawapat.b@covest.finance>

* fix(editor): keep chat visible after closing Markdown tabs

Count remaining unified chat tabs before clearing workspace selection during editor close.

Related: https://github.com/stablyai/orca/pull/24273, https://github.com/stablyai/orca/pull/23760

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* Honor typed starting numbers in chat ordered lists

Forward the existing parsed ordered-list start attribute to both chat Markdown renderers.

Related: https://github.com/stablyai/orca/pull/19765

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Frederic Barthelemy <git@fbartho.com>

* Normalize base source once while checking changed-code diagnostics (#24557)

Reuse the exact existing moved-code matching algorithm with run-local lazy normalization of immutable base source blocks across diagnostics.

* Support real OpenCode sessions in native Chat (#24647)

* Use bounded OpenCode context for vault session continuation

OpenCode database and synthetic row paths are not text transcripts. Use the
vault preview or captured pane context, preserving actual transcript paths
containing a hash and supporting both OpenCode lanes and Windows paths.

Adapted the intent of #11859 and extended it to actual installed v2 vault rows.

Co-authored-by: mrcha033 <mrcha033@users.noreply.github.com>

* Read real OpenCode sessions in terminal-backed native Chat

Reuse the bounded AI Vault SQLite worker for v1 and v2 session pages and live updates. Keep terminal input as the real execution path and pace OpenCode Stop through its two-Escape interrupt.

Co-authored-by: xodmd45-ctrl <xodmd45-ctrl@users.noreply.github.com>

* fix(opencode): publish approval cards for permission requests

* Send OpenCode native approval through its Enter selector

* Resolve mobile Chat readability for folder workspaces

* Bound OpenCode part batches and preserve v2 image attachments

* Prefer live migrated OpenCode sessions over legacy copies

* Consolidate mobile Chat eligibility test imports

* Consolidate OpenCode SQLite protocol type imports

* Update native chat settings contract for both OpenCode agents

* fix(native-chat): reconcile bounded OpenCode transcript reads

* fix(native-chat): dispatch OpenCode questions safely

* fix(native-chat): keep native discovery and transcript windows current

* feat(accounts): link standalone GLM Coding Plans (#24618)

* feat(accounts): link standalone GLM Coding Plans

Adapt the reviewed GLM accounts contribution to current main, retain Antigravity behavior, guard late credential results, expose storage protection, and redact quota errors.

Co-authored-by: Luchong <lu740528977@gmail.com>

* fix(accounts): retain GLM credential results during quota refresh

* fix(accounts): make GLM credential editing desktop-only

* fix(accounts): mirror the host GLM site in paired clients

* fix(accounts): report unknown GLM host details and split web settings tests

Apply the independently reviewed Accounts correction from697284a without the v2 adapter commits. Preserve the saved-key store and serialized write behavior.

* fix(zcode): ship required GLM account translation entries

* chore: record GLM reconciliation hook validation

* chore: validate installed GLM commit hooks

* test: complete GLM account fixtures and web API inventory

---------

Co-authored-by: Luchong <lu740528977@gmail.com>

* fix(native-chat): route transcript requests through shared SQLite worker

* fix(ci): prevent concurrent pnpm refresh during mobile typechecks (#24776)

* fix(ci): run mobile typechecks without concurrent dependency refresh

* test(ci): check effective Linux E2E package list

* test(ci): preserve the mobile production compiler barrier

---------

Co-authored-by: Orca Integration Recovery <orca-validation@invalid.example>

* test(terminal): restore the live fish fixture prerequisites (#24947)

A restored pane waits for the initial status replay before subscribing to
PTY output. This fixture never settled that replay, so fish printed its
mode-2031 arm before the renderer connected. Its PTY API also omitted the
reset-input listener required by the serializer, aborting attachment.

Settle and dispose the existing startup-snapshot registration and provide
the same reset-listener mock used by the other PTY tests. The real fish
child-stdin assertions and timeouts remain unchanged. No production change.

* fix(shortcuts): defer TUI editing chords in terminal-first mode (#24640)

Restack the original focused change onto current main, preserving every owned source and test blob and the merged CI contract and journal cleanup fixes.

Original-commit: f707cde14ab8cb2670b4076916cdfb7e28c79983
fix(shortcuts): defer TUI editing chords in terminal-first mode

Original-commit: 0c6348e49e0d968e0170961d294a018adceaa9f3
docs(shortcuts): describe deferred preview terminal chords

Original-commit: be62c1b6c6b305cb8091161c1ccdd943a6e1d470
Align worktree history shortcut metadata with terminal conflict policy

Restacked-from: be62c1b6c6b305cb8091161c1ccdd943a6e1d470
Restacked-onto: f7b1f9d8be14d12244957ee0b710a3482ec62383

* Register supervised Qoder China and Qwen Code (#24616)

* Add Qoder session history and search with real CLI coverage

* Allow the real Qoder marker file to end with a newline

* Keep Qoder tool output out of history previews and search

* Keep Qoder search pages readable by older clients

* Verify persisted Qoder history after a real generated and resumed task

* Negotiate Qoder filters before searching an older execution host

* Combine search client imports for the CI plugin gate

* Keep the relay search oracle aligned with legacy agent filtering

* Register supervised Qoder China and Qwen lifecycle integration

* Cover Qoder China mobile assets and mixed-host resume gates

* Verify Qoder provider tags against the older released wire parser

* Verify China and Qwen keep independent Windows hook scripts

* Verify Qoder registrations against the installed older Windows release

* test(qoder): align search capability contracts and pin old-host fencing

* fix(qoder): rank exact picker identities and command aliases first

* test(qoder): preserve the regional CLI shared icon expectation

Keep the full bundled-asset and no-remote-image checks, with an explicit
shared-logo basename for Qoder China. The map also works with older
catalog type unions.

* fix(qoder): align China catalog entry with fallback order

---------

Co-authored-by: Orca Integration Recovery <orca-validation@invalid.example>

* Use the measured pnpm lookup policy automatically in hosted root CI (#24951)

* Select lookup automatically for the measured hosted root-install profile

* Record hosted automatic-mode cold cache publication proof

* fix(native-chat): keep OpenCode history usable at read limits

Continue past failed database probes while preserving discovery cancellation.
Verify rows displaced by a capped tail before deciding whether to replace history.
Represent oversized v1/v2 rows with the existing omission text and stable cursors.

* Continue Antigravity IDE and 2.0 history in new CLI conversations (#24692)

* feat(antigravity): bridge IDE history into new CLI conversations

* fix(antigravity): preserve fresh-launch model and environment for IDE references

* fix(antigravity): forward IDE history opt-in through desktop IPC

* fix(antigravity): rebuild remote IDE reference startup on its host

* fix(antigravity): register IDE continuation action labels

* fix(antigravity): confine IDE references and bound metadata reads

* fix(antigravity): localize IDE continuation badges

* Preserve scanner service cache assertions and refresh Antigravity opening metadata

* Preserve Antigravity opening joins and target folder runtime authority

* fix(opencode): retry timed-out SSH plugin updates (#24666)

Preserve bounded retry behavior and the current-main status-envelope fields.

Original-PR: #24124
Reviewed-source: 103144f9c5029f9217f64970271a5b7f69d3f823

Co-authored-by: Justas Brazauskas <brazauskasjustas@gmail.com>

* fix(opencode): keep Go credentials private and resolve backend keys (#24615)

Preserve the complete credential storage, migration, IPC, Settings and rate-limit refresh change alongside standalone GLM plans, current-main database diagnostics and the reviewed unknown-backend environment correction. Keep native discovery cancellation third and selected environment fourth.

Original-topic-commit: 7903f1cddbc08fe1179f8bd964fff3dcb0e5d020
Original-topic-commit: 588117b5cf1dd57e2310c80068e3ddcc9f9044ec
Original-topic-commit: dedd4f8c862a961393977dc3c2547f049391b509
Original-topic-commit: 6645dae104ee5271139fcc0e9564d9223b74835d
Original-topic-commit: a25b80c02c1af7830b0e6a65e72d965b3ad98276
Restacked-from: a25b80c02c1af7830b0e6a65e72d965b3ad98276
Restacked-onto: b032867021c7ef1436ca606559e9d786580a84dc

Co-authored-by: kespineira <kespineira@users.noreply.github.com>
Co-authored-by: kevimux <kevimux@users.noreply.github.com>
Reported-by: pullfrog
Reviewed-full-source: 849fe093073f4c1606bd65d79a0c725d955d0d1f
Native-helper-source: 80dbe23237db191c1e6280001c7e0563f3ca8846


Reviewed-full-current-source: 36acb57d44adb3d378c0289c8c15f7da0fda214c

---------

Co-authored-by: mrcha033 <mrcha033@users.noreply.github.com>
Co-authored-by: xodmd45-ctrl <xodmd45-ctrl@users.noreply.github.com>
Co-authored-by: Luchong <lu740528977@gmail.com>
Co-authored-by: Orca Integration Recovery <orca-validation@invalid.example>
Co-authored-by: Justas Brazauskas <brazauskasjustas@gmail.com>

* Drain removal fixture jobs before resetting and deleting their records (#24977)

* Reuse measured Electron preparation for current Terminal Perf refs (#24968)

* feat(jcode): add Jcode as a supported TUI agent with managed hooks

Ports PR #10521 onto current main: agent catalog, managed hook service,
agent-status listener, session resume, AI Vault parser, per-pane daemon
isolation, and Source Control AI support.

Co-authored-by: Neil <neil@stably.ai>

* feat(jcode): evidence-backed status pipeline (turn_start, live pre_tool, questions)

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>

* fix(jcode): register vault fixture, dynamic model discovery, script refresher

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>

* fix(jcode): keep finished-turn detail so completion notifications fire

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>

* fix(jcode): show the prompt in agent rows instead of jcode's repainting title

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>

* fix(jcode): pre-warm the per-pane daemon so a cold runtime dir cannot time out

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>

* fix(jcode): stop the OSC color skip from crashing every pane connect

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>

* refactor(jcode): fold three reverse-scan copies into one, reuse the shared hook POST

The jcode journal reader, the Claude transcript reader and the Command Code
transcript reader each carried their own copy of the same reverse chunked line
scan; they now share one tested helper. jcode's managed hook script drops its
hand-rolled curl for buildPosixAgentHookPostCommand, which also gains it the
raw-JSON transport and the --noproxy guard the bespoke copy was missing.

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>

* fix(jcode): narrow dynamic reads with predicates, pin the Windows hook shape

CI's anti-slop audit rejects Reflect.get: parse dynamic input into a named type
instead. Adds Windows script-shape tests too, since Windows is the platform this
change could not be exercised on directly.

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>

* test(jcode): measure the gate against the synchronous path, not the clock

The absolute 1s bound was the flake CI shard 3/8 hit: it is tight enough to catch
a synchronous gate on an idle laptop and too tight on a loaded runner. Measuring
the same POST both ways on the same machine makes the claim a ratio, which is what
the test is actually about. Mutation-checked: a synchronous gate reads 6120ms
against a 1517ms observer.

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>

* test(jcode): drop the wall-clock gate assertion

The bound was machine-speed sensitive and flaked on CI shard 3/8 at 1525ms. The
structural assertions (detached gate branch, foreground observer branch) and the
no-hang stdin drain cover the same contract without a timer.

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>

* fix(jcode): address CodeRabbit review on #22539

- Windows posted no payload at all: the shared builder reads `payload@-` from
  stdin, which the gate has already drained and observer hooks never receive, so
  every Windows event was dropped. Write the env var to a temp file and pipe it.
- The daemon pre-warm never fired for daemon-host spawns, which is the default
  local path; it now runs there too, and from the final env so the daemon gets the
  hook port and token.
- A failed runtime-dir mkdir took down every local terminal, jcode or not.
- removeJcodeManagedHooks matched the raw line, so a user hook whose comment
  mentioned the managed script was deleted; matching on Windows never worked.
- A managed entry left by a copied home or a platform switch is now repointed
  instead of being reported as user-owned forever.
- The OSC colour skip only checked launchAgent, so a command- or telemetry-named
  jcode pane still leaked the reply into its composer.
- `['hooks']` and a commented scalar are recognised, instead of appending a
  second [hooks] table that makes jcode reject the whole config.
- A failed tool's error is marked as tool output rather than agent prose.
- The vault keeps a session's stored name, counts its tokens, and skips
  background_task and [Scheduled task] turns.

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>

* fix(jcode): read the journal once per turn, key prompts by byte offset

The jcode prompt reader ran a synchronous bounded file scan plus a JSON
parse on every hook event. jcode blocks on pre_tool, so a turn that ran
four tools charged the user eight scans of latency it did not need — the
prompt cannot change inside a turn.

- Cache the journal read per pane, refreshed on the turn boundary that
  can change it. The cache holds the whole evidence record, since
  hasExplicitUserPrompt needs the transcript-evidence flag and not just
  the text, and it joins the existing pane-scoped lifecycle (close,
  rename, reset) rather than living in a module singleton.
- Key a journal prompt by its absolute byte offset instead of its
  region-local line index. The backward scan windows the file from EOF,
  so appending shifted every boundary and reminted the key for a prompt
  that never moved; a repeated turn_end then slipped past the same-hash
  dedupe as a second done event with duplicate telemetry.
- Pin the platform in the daemon pre-warm tests. The pre-warm is a no-op
  off POSIX, so the dedupe and retry cases would have passed vacuously
  on a Windows runner.

Co-authored-by: czzczz <chanzrz_zbf@foxmail.com>

* fix(jcode): quote the managed hook path, drop tools from patch prompts

Three fixes, all on paths this PR could not exercise locally.

The managed hook command was stored as a bare path. jcode tokenizes that
string shell-style before exec'ing it directly (parse_hook_command,
crates/jcode-terminal-launch/src/lib.rs): unquoted whitespace splits, and
every unquoted backslash is consumed as an escape. So on Windows
`C:\Users\me\.orca\agent-hooks\jcode-hook.cmd` reached exec as
`C:Usersme.orcaagent-hooksjcode-hook.cmd` and no hook fired at all, and a
POSIX home with a space split into two arguments. Store the path
single-quoted (verbatim, backslashes included), falling back to double
quotes for a path containing a single quote. Existing bare entries are
already repointed by the stale-key path, and getStatus accepts both forms
so the repair is not reported as a user-owned hook. The quoting helper was
previously dead code that only tests called; the three production sites
now use it. isJcodeManagedCommand also normalizes separators, since a
`/`-only needle never matched a Windows entry.

Commit-message generation feeds a staged patch to `jcode run` as the
prompt — attacker-influenced text — while jcode's default profile exposes
shell, read, write, and MCP. Pass `--tool-profile none`, which resolves to
an empty allowed-tool set in jcode's config (base_allowed_t…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant