* ci(release): publish main-process source maps with each release
Desktop bundles ship minified, and packaging drops out/**/*.map from
app.asar, so a stack trace from a released build cannot be mapped back to
source. main builds with sourcemap:'hidden' — the maps exist in CI but were
never published anywhere.
Zip them on the linux-x64 leg and upload to the draft release as
orca-sourcemaps-<tag>.zip (33.7MB raw, ~8MB zipped, 69 files). The main
bundle is platform-independent, so one leg covers the whole release. The
step fails loudly if no maps are found, so a regression of build.sourcemap
breaks the release instead of silently shipping undecodable builds.
* fix(release): stage source map bundle outside the checkout
Every entry in electron-builder's `files` is a negation, so app-builder hits
containsOnlyIgnore() and prepends `**/*` (fileMatcher.js:285). A zip left in
the workspace root would have been packed into the linux-x64 app.asar,
growing that platform's installers by ~8MB and diverging them from arm64 —
the same hazard the '!pr-evidence' exclusion already guards against.
Stage it in $RUNNER_TEMP, matching the release-state file at :444.
* perf(build): minify desktop JavaScript bundles
* perf(build): minify with rolldown's oxc and emit hidden main source maps
'esbuild' made rolldown disable its own minifier and re-print every chunk
through esbuild, which is not a declared dependency and resolves only via
pnpm's shamefullyHoist from electron-vite's tree (0.25.12 against a declared
peer of ^0.27.0). Switching to rolldown's in-process 'oxc' minifier drops
that second pass: main+renderer build falls 23.2s -> 11.9s and ships ~2.7MB
less JavaScript.
keepNames is dropped with it — it cost ~1.5MB and only recovered function
names. main now builds with sourcemap:'hidden', which restores names *and*
locations without emitting a sourceMappingURL. Packaging excludes
out/**/*.map so app.asar is unaffected; release CI publishes the maps.
Track scroll-restore generation to invalidate stale callbacks that were
resetting the scroll position to 0 when reopening a detail page. Prevent
restoration while a detail page is open.
Update automation test to use runtime.call RPC instead of removed preload
CRUD method. Hide browser import hint in E2E profile to prevent overlay from
intercepting test setup clicks.
Validate scheduled values match current state before executing idle
timeout callbacks. Use useLayoutEffect to synchronously update refs,
preventing outdated searches when rapid keystrokes overwrite timers.
* refactor(agent-hooks): drop the unused per-agent hook status IPC surface
No renderer, CLI, or mobile caller invoked window.api.agentHooks.*Status; main
already reads install status through MANAGED_AGENT_HOOK_STATUS_READERS. The
14 handlers had also drifted (kimiStatus existed in main/preload but not in
AgentHooksApi or the web stub).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(tui-agent-config): default launchCmd and expectedProcess to detectCmd
32 of 36 entries repeated the binary name three times. Entries are now
authored in a source form where both default to detectCmd and resolved once
at module load, so TUI_AGENT_CONFIG keeps its exact shape for consumers
(verified equal to the previous table).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(mobile): derive the agent order, labels, and picker from src/shared
The mobile mirror (and its regex-over-desktop-source parity test) predates
mobile importing runtime values from src/shared, which it now does in a dozen
modules. Only the favicon-domain map stays mobile-local because desktop's lives
in the renderer catalog next to bundled ?url imports. The parity test now
imports the real registries and also checks label parity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test(web): align preload surface after hook IPC removal
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Review follow-ups on the create-field shaping:
- Seed only `reporter`. isVisibleJiraCreateField matches every required
non-system field, so the previous filter also pre-filled required custom
user pickers (Reviewer, Requested by) that Jira never defaults.
- Skip the seed when the target project is on another site. The viewer
comes from the active site, and the host shapes against the target's
client, so a foreign accountId is rejected on Cloud and can silently
resolve to a different person by username on Server/DC.
- Render JiraUserPicker only for scalar user fields. It holds one user, so
an array-of-user field collapsed to a single member; those keep the
existing comma-separated text path, which still reaches toUserFieldValue's
array branch.
Adds docstrings across the touched Jira functions to satisfy the
docstring-coverage pre-merge check.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HdMzQN6T3jRVahCK2sNyur
- Jira rejects a bare string for reporter/user-picker fields on issue
create, so shape customFields values into {accountId}/{name} objects
for keys the caller flags via userFieldKeys.
- Seed required user fields with the authenticated viewer by default
and add a searchable user picker (jira.searchUsers) so users aren't
forced into free text for reporter/custom user fields.
* fix(agents): keep OMP identity and forward ask/approval events (STA-4130)
A live OMP pane was re-owned as Pi because the generic pi-compatible
fallback always won, ask events blocked without a question payload, and
OMP suppressed tool_approval_* unless an extension registered handlers.
Mark Pi as the title-group fallback so a specific OMP identity is not
downgraded, publish OMP ask input as the existing questions envelope, and
forward tool_approval_requested/resolved onto blocked/working.
STA-4130
Related to #14278
Co-authored-by: devatnull <59279509+devatnull@users.noreply.github.com>
* fix(agents): keep launch Pi ownership over OMP wrapper frames (STA-4130)
The pi-compatible fallback treated every generic Pi owner as inferred, so an
explicit launch-Pi pane (and a launchless Pi pane with an OMP-shaped title)
was re-owned as OMP. Launch provenance now stays authoritative; only an
inferred status-frame owner yields to a specific sibling, and same-group
titles no longer count as reuse.
STA-4130
* fix(agents): drop Pi wrapper idle titles while OMP hook is active (STA-4130)
Title-completion suppression compared pick-a-winner ownership, so a Pi ready
frame looked like a different agent than a live OMP hook and fired a spurious
task-complete notification. Reuse checks now use the title-identity group.
STA-4130
* fix(agents): restore OMP approval forwarding after merge
* fix(agents): restore title-owner API after merge
* test(agents): update identity inventory ratchet
---------
Co-authored-by: devatnull <59279509+devatnull@users.noreply.github.com>
Co-authored-by: Merge Sim <sim@local>
* fix(omp): read Pi/OMP static state-title markers and retire stale spinners
OMP 17.2.12 replaced its animated braille title frames with static markers
on WSL/ConPTY (`π : working`, `π > idle`, `π ! needs input`). Orca read all
three as idle, so a working OMP pane lost its status, and a synthetic title
spinner started by an earlier hook kept rotating after its status row was
gone.
Classify the markers from one shared table so a later upstream punctuation
change is a row, not a reparse, and stop the spinner when the hook row it
stands in for is cleared or dismissed.
Fixes#13890
* test(omp): preserve static state titles during normalization
---------
Co-authored-by: Merge Sim <sim@local>
* feat(browser): edit a page annotation's comment and intent inline in the tray
Fixing a typo in a browser annotation required deleting it and re-picking
the element in the page. Each tray row now has a hover-revealed edit
button that swaps the row to an inline editor (comment textarea seeded
with the current text, intent toggle, Save/Cancel), reusing the compose
card's submit shortcut and length budget. Edits route through a new
updateBrowserPageAnnotation store action that no-ops on a missing id and
sanitizes the merged annotation exactly like the add path.
Escape inside the editor cancels only the row edit: the annotate mode's
window-level capture listener now exempts the edit container, since
stopPropagation from a descendant cannot reach a capture listener.
Editing is deliberately limited to comment and intent: element targets,
cross-navigation persistence, and the prompt builder are untouched (the
builder reads live off the array, so edited text flows through).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017rEaTnSaSneEMEJvebzM53
* test(browser): pin the annotate-mode Escape exemption for annotation edits
The data-slot annotation-edit clause in useGrabMode's capture keydown
listener had no test that dispatched a keydown through it, so deleting
the clause left the suite green. These tests invoke the real registered
capture handler with an Escape whose target sits inside (and outside) an
annotation-edit container; the inside case uses a button, which
isEditableKeyboardTarget does not cover, so only the exemption clause
can keep grab mode alive. Removing the clause now fails the suite.
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>