Commit Graph
110 Commits
Author SHA1 Message Date
Jinwoo-H 3577dc2e15 Merge branch 'ota-w-git' of /tmp/orca-fix/git into ota-wave-integrate
# Conflicts:
#	mobile/src/mobile-web/hosted-ios-source-control-review-journey.test.ts
#	src/mobile-web/src/mobile-web-source-control-sync-request-client.test.ts
#	src/shared/mobile-web/bridge-operation-echo-census.test.ts
#	src/shared/mobile-web/bridge-operation-registry-census.test.ts
2026-09-07 16:23:01 -04:00
Jinwoo-H 296ff0f88f test(mobile): read committed generations instead of an activation file
The device harnesses polled `activation.json` to learn which build was live.
A host now keeps exactly one committed generation, so that directory is the
record. The crash-loop and corrupt-cache drills only ever asserted the A/B
rollback and are removed with it.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-07 16:02:29 -04:00
Jinwoo-H f0a007c289 fix(mobile): identify a hosted bridge error by the Desktop method it named
The Source Control journey looked for a `sourceControl.reviewOpen` bridge
error, which the generic host lane no longer reports under that name. The
observation now records the method a host request named, and the journey
matches on it.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-07 15:45:28 -04:00
Jinwoo-H 140c70df2c refactor(mobile): replace the iOS staged-write protocol with two calls
The store now takes one complete asset per call and one commit that verifies
the staged tree against the manifest, renames it into place, and keeps a single
generation per host under a four-host LRU cap. That retires stage ids, per-chunk
hashes, byte reservation, the A/B activation record, and the exact-JSON scanner:
the build id is the sha256 of the manifest bytes, so the directory name
authenticates the manifest and the manifest authenticates every asset.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-07 14:58:01 -04:00
Jinwoo-H 70298a5cfa test(mobile): give the host-origin Source Control journey a real oracle
Under --adversarial-content the journey had no native baseline, so it derived
the expected changed-file label from the page it was checking and then asserted
the page contained it. That assertion could never fail. The expected label now
comes from the adversarial repository fixture that created the changed file, and
the journey refuses to run when neither an independent path nor a native
baseline is available.

The workspace-row tap that follows the journey moved next to it, so the step
owns the row it returns to and the runner stays under the .mjs line ceiling.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-07 04:40:10 -04:00
Jinwoo-H 15d19c308b feat(mobile): move mobile sessions and settings into the hosted page
Session snapshot/feed/activate/close/createBrowser/createTerminal,
quick commands and agent options now run as Desktop mobileWeb.* adapters
behind the generic host-request forwarder instead of shell translators.
Voice, notification, terminal, browser, chat, About and diagnostics
settings render as hosted page routes with native-*/web-* operation
backends. Adds the hosted WebView e2e journeys used to validate them.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-07 04:16:39 -04:00
Jinwoo-H 4f95f2f31d test(mobile): include Terminal preference evidence in iOS report
Record the verified Terminal consumer journey alongside Chat and Browser results. The optional OTA crash-loop fixture is deferred outside the worktree under the requested YAGNI scope.
2026-09-06 21:33:19 -04:00
Jinwoo-H f2909d3539 test(mobile): verify hosted Terminal preferences in session consumers
Exercise text scale, autocorrect and custom shortcut persistence through the real hosted settings and session. Reuse picker and terminal inspection logic and restore original preferences. Full iOS adversarial run passed with ok:true against build eab7fd8f5eb4a37e593526e90dcc5105552691db072da8a982cd1ed30784a2e3; all code gates and export passed.
2026-09-06 21:30:49 -04:00
Jinwoo-H dd93e3b007 feat(mobile-web): host browser preferences and the settings menu
Share native presentation and apply paired-host page preferences to terminal link behavior. Preserve inherited native values, handle storage failures, and verify saved values plus Chat route recovery through a real iOS WebView restart.
2026-09-06 20:56:20 -04:00
Jinwoo-H 9be7d26db9 feat(mobile-web): host chat preferences in the page
Reuse the Chat UI settings screen with paired-host page storage and grant-gated navigation. Verify persistence and theme rendering in the full iOS adversarial journey; retain native recovery presentation.
2026-09-06 20:32:21 -04:00
Jinwoo-H 79f54a8b49 fix(mobile): wait for adversarial review content and route readiness
Wait for the diff body rather than just Review controls, and handle Back through Source Control before opening file previews. iOS confirms terminal links and rendered adversarial diff; the full unattended journey remains tracked. Required gates pass in native-chat-read-gates.
2026-09-06 19:01:27 -04:00
Jinwoo-H 42c031d85e fix(mobile-web): preserve chat bindings across unavailable host reads
Keep authority on failed or malformed tab snapshots. Exercise headless terminal file links through line-addressed hosted previews, since renderer-backed file tabs require a Desktop renderer. Record the observed native tap and host resolution evidence.
2026-09-06 18:31:37 -04:00
Jinwoo-H d39be4951d fix(mobile): repair hosted journey accessibility and route checks
Label standalone toolbar actions, match WebView accessibility values, and fence workspace return checks by pathname. Reuse Android labelled navigation and support adversarial journeys without native screenshot baselines. Record passing iOS file parity and the unresolved terminal file-link gate on both platforms.
2026-09-06 18:11:18 -04:00
Jinwoo-H b78660541d chore(mobile): split the download-measurement harness under max-lines
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-03 04:07:21 -04:00
Jinwoo-H b3c416963c Merge branch 'worktree-agent-a5d9fcc87bd472be9' into mobile-rearch
# Conflicts:
#	mobile/app/hybrid.tsx
#	mobile/src/mobile-web/use-mobile-web-package-recovery.ts
2026-09-03 04:07:05 -04:00
Jinwoo-H c6d79aa7eb perf(mobile): pipeline and widen mobile-web package reads
The hybrid app pulled its 9.1 MiB mobile-web package one 48 KiB chunk per RPC
round trip, strictly serially, and 99.3% of the package is a single 9.5 MB
script — so the whole download was 245 sequential round trips against whatever
the relay path's latency happened to be. Measured on the real package over the
real mobile relay client with a 120 ms round trip: 31.7 s (0.30 MB/s).

Two changes, both negotiated:

- the downloader now keeps up to MOBILE_WEB_PACKAGE_MAX_CONCURRENT_READS reads
  in flight across the whole manifest while still draining to the stager in
  offset order (the native stage appends at the file's current length), and
  narrows the window instead of failing when a host answers
  mobile_web_package_read_limited;
- mobileWeb.package.asset.gzip takes an optional `length` so one read answers up
  to eight chunks. The params schema is strict, so older hosts reject the field —
  it is gated on the new mobileWeb.package.range.v1 capability, and the client
  still splits the range into 48 KiB stage writes.

Same package, same harness, relay path: 31.7 s -> 2.8 s at 120 ms RTT and
62.9 s -> 5.5 s at 250 ms RTT, with 245 requests down to 76.

The download still dies when the app is backgrounded past
RELAY_BACKGROUND_GRACE_MS — the session suspends, the refresh effect aborts, and
the stage is discarded — so the progress panel now says to keep the app open.
Resuming from the staged offset needs a native stage-reopen API on both
platforms and is not attempted here.

mobile/scripts/measure-mobile-web-package-download.mjs drives the real
downloader over both the direct and relay mobile clients with an injectable
round trip, which is where every number above comes from.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-03 03:50:20 -04:00
Jinwoo-H 20a499baa5 test(mobile-e2e): name both landmarks when screenshot parity fails
The failure printed only landmarkDelta, which cannot say which side moved. The
two landmarks come from different sources, a native accessibility frame and a
hosted DOM rect, so the absolute pair is what makes the next failure readable.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-02 02:07:21 -04:00
Jinwoo-H 06a2dd7b5b Revert "read the native landmark after the route settles"
The landmark delta is bit-identical across the run before the change and the
run after it (0.047498512585812364 both times), so re-reading after the settle
changes nothing and the animation rationale was wrong. Reverting rather than
leaving an inert change carrying a disproved explanation.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-02 02:05:21 -04:00
Jinwoo-H 5e39d8647c test(mobile-e2e): assert session-origin reviewOpen matches native on this host
Opening a changed file from a session-origin Source Control sends
files.openDiff, which needs a renderer notifier. The e2e pairs against
`orca serve --mobile-pairing`, which has none, so the host answers
renderer_unavailable on native and hybrid alike. The journey asserted the diff
tab unconditionally and could never pass.

The native baseline now probes the same session-origin path and records what
the paired host answered. The hosted journey takes whichever arrives first, the
diff route or the bridge error, and pins it against the native result, so the
claim is "hybrid matches native on this host" rather than "hybrid fails". On a
full desktop the diff route wins and reviewOpen.headless records false.

Kept as evidence, not fixed: the hybrid banner reads "Source control action
failed" where native names renderer_unavailable.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-02 01:45:51 -04:00
Jinwoo-H 4dc2229283 test(mobile-e2e): capture a native journey stop only once its tree repeats
A single accessibility read caught the Tasks list mid-load on one client and a
second, transient xterm helper node on the other, and both read as client
differences. Poll until two consecutive volatile-free reads match, then
screenshot. Re-running the A/B with this in place left the twelve stops
identical except for live GitHub issue content.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-02 01:35:30 -04:00
Jinwoo-H 909edbb68a fix(mobile-e2e): read the native landmark after the route settles
The host-origin Source Control route animates in, so captureNativeRoute read
its landmark before the 500ms settle and screenshotted after. The parity check
then failed on landmarkDelta.y 0.0475 against a 0.005 budget while the pixels
agreed at 0.0121 against 0.03. Measured on a live hybrid session: the DOM point
and the accessibility point agree to 0.0000064, so the coordinate spaces were
never the problem.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-02 01:15:12 -04:00
Jinwoo-H 8e668a7531 test(mobile-e2e): drop the retired synthetic-resume gate and add a native A/B capture
The Agent History journeys still asserted "Failed to resume session." for a
page-synthesized resume. mr-gesture-delete removed that gate on purpose, so the
synthetic click now resumes and the wait timed out on the resumed session route.
Both journeys keep the native-touch resume.

Adds a native journey capture that walks the six baseline journeys recording
ordered accessibility labels plus a screenshot per stop, a diff over two
captures, and an ORCA_E2E_MOBILE_METRO_DIR override so an old client checkout
can serve Metro while the paired desktop runtime stays on this one.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-02 00:42:59 -04:00
Jinwoo-H 3db98b70f7 fix(mobile-e2e): hold the simulator long press across two gesture commands
One `orca emulator gesture` call delivers its whole point list as a single
batch, so the 62-point begin/hold/end sequence landed as a tap: the native
Source Control baseline long-pressed the workspace row, navigated into the
session instead, and failed on a missing "Source Control" control. Split the
press across two commands, hold, poll for the settled control while the touch
is down, and always lift.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-02 00:32:06 -04:00
Jinwoo-H d156826131 refactor(mobile): delete the mobile-web user-gesture window
The hybrid WebView required a recent native-observed touch before a bridge
capability could run. A scroll armed the window, so it gated nothing an
attacker on the first-party page could not already reach, and no peer hybrid
framework (Capacitor, Cordova, RN WebView) gates bridge calls this way.

Removes the gesture module, its React authority hook, the shared requirement
and its census, and all 20 gate sites: native.alert, clipboard write, external
link open, terminal text-scale and custom-key updates, dictation start and
model management, account select and reset-credit consume, agent-history
resume, terminal clipboard paste and image attach, navigation reconnect,
removeHost and terminal-settings route, and both workspace-creation writes.
Each operation now just runs.

The AppState foreground reporting the gesture hook also carried moves to
use-mobile-web-app-foreground-authority. permission_required stays in the
bridge error enum: it parses inbound responses, so narrowing it would break a
new page paired with an older shell.

Drops the G3 gesture-window e2e probe and renames its runner to
run-hosted-ios-webview-app-bound-probe.mjs, which keeps the app-bound probe.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-01 23:49:03 -04:00
Jinwoo-H 75205167a8 fix(mobile): drop the inert app-bound navigation limit from the iOS shell
No WKAppBoundDomains is declared, and an A/B native rebuild showed identical
behavior with and without the flag: the shell's navigation delegate refuses
external navigation either way. The probe script stays as the regression check.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-01 23:34:45 -04:00
Jinwoo-H 1e5774022f Merge branch 'mr-residue' into mobile-rearch 2026-09-01 23:18:00 -04:00
Jinwoo-H c8f7586f54 refactor: strip PR #10179 residue from the mobile rearchitecture branch
#10179 ("bound OOM-prone accumulators") was reverted on main by #10255, but
the hybrid WebView rewrite carried parts of it forward wherever the revert
could not apply cleanly. Remove those, keeping the hybrid work that had
merely adopted them.

Deleted the bounded mobile RPC queues, ledgers, budgets and JSON admission;
the bounded emulator-script readers; the transcript record buffer and
retention window; and the bounded relay/SSH directory and markdown-document
listing modules. Restored main's connection log store, E2EE v2 channel,
daemon spawner and relay error codes, and reverted the transcript readers'
page and drain budgets.

Kept, and rewired onto main's modules: the terminal binary frame path, the
hosted privacy redactions, the transcript file-source plumbing, and the
chunked file and terminal-artifact reads the hosted client depends on.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-01 23:02:11 -04:00
Jinwoo-H 696b83186f test(mobile): probe the hybrid WebView gesture window and app-bound flag
Two security-review questions about the hybrid iOS shell needed measurement
rather than reading: which native touches arm the 5s user-gesture window that
privileged page requests spend, and whether limitsNavigationsToAppBoundDomains
does anything while app.json declares no WKAppBoundDomains key.

The gesture probe drives clipboardWrite, the cheapest gesture-gated mutation,
through the page bridge after each candidate arming action and records whether
the shell granted or denied it. The app-bound probe asks the page to navigate
to an external https origin and records who refuses it: the shell's navigation
delegate raises a native warning banner, while an app-bound refusal would fail
the provisional navigation inside WebKit with no delegate decision.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-01 23:01:06 -04:00
Jinwoo-H 5735189af7 test(mobile): fix hosted iOS e2e harness and root test triage
Hosted iOS security e2e (three branch-only harness bugs):
- `simctl privacy grant` terminates the app; the relaunch cold-resumes
  straight onto the session route, so skip workspace-row activation when
  the hybrid handoff already landed on /session/. Activation failures now
  name the document href.
- Uploaded-path regex fused two abutting orca-paste-*.png paths; use a
  lazy segment quantifier.
- Photos orders by capture date, which addmedia takes from file birth
  time; stage a freshly written fixture copy (copyFile clones birth time
  on APFS) so "last Photo" is the fixture.

Root tests:
- Allowlist walker skips -test-fakes / -test-fixture(s) / .test-support
  sources, which are not mobile call sites.
- Drop the height-only OSC-8 test: main's #17759 clears restored ranges
  on any dimension change and pins it.
- Drop serve-update-handoff-startup-order.test.ts: main pins the same
  order against main-process-preflight.ts.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-01 21:17:38 -04:00
Jinwoo-H 5746d6f1dc test(mobile): arm a native gesture before the hosted alert probe; split the task project client
native.alert is now gesture-gated, so the simulator journey taps the page
before posting the probe. The task project request client sat one line over
its max-lines cap; its project echo check moves to its own module.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-01 19:24:33 -04:00
Jinwoo-H b551c47173 fix(mobile): harden hosted web runtime boundaries 2026-08-30 22:31:44 -04:00
Jinwoo-H 66a9d9086e Merge remote-tracking branch 'origin/main' into mobile-rearch
# Conflicts:
#	.gitignore
#	config/scripts/pr-code-change-scope.mjs
#	config/scripts/pr-code-change-scope.test.mjs
#	mobile/app/connection-log.tsx
#	mobile/app/h/[hostId]/index.tsx
#	mobile/app/h/[hostId]/session/[worktreeId].tsx
#	mobile/app/pair-scan.tsx
#	mobile/src/browser/MobileBrowserPane.tsx
#	mobile/src/components/CustomKeyModal.tsx
#	mobile/src/components/NewWorktreeModal.test.tsx
#	mobile/src/components/NewWorktreeModal.tsx
#	mobile/src/components/mobile-rich-markdown-editor-html.ts
#	mobile/src/diagnostics/connection-diagnostics-report.test.ts
#	mobile/src/diagnostics/connection-diagnostics-report.ts
#	mobile/src/tasks/use-smart-workspace-source.ts
#	mobile/src/tasks/worktree-create-capability.ts
#	mobile/src/terminal/use-terminal-live-accessory-input-commit.ts
#	mobile/src/transport/connection-log-buffer.ts
#	mobile/src/transport/direct-rpc-client.ts
#	mobile/src/transport/host-status-gates.ts
#	mobile/src/transport/mobile-relay-rpc-session.ts
#	mobile/src/transport/rpc-client-socket-close-controller.ts
#	mobile/src/transport/rpc-client-socket-factory.ts
#	mobile/src/transport/rpc-client-socket-session.ts
#	src/main/providers/filesystem-provider-contract.ts
#	src/main/providers/ssh-filesystem-provider.ts
#	src/main/runtime/rpc/methods/index.ts
#	src/relay/fs-handler.ts
#	tests/e2e/helpers/docker-ssh-relay-connection.ts
2026-08-29 04:24:00 -04:00
Neil 7ee8b5e1a6 Refactor lower max-lines modules (#16760) 2026-08-27 16:10:51 -07:00
Jinwoo-H d0437be0d1 fix(mobile): launch hosted export without pnpm shim 2026-08-23 21:00:59 -04:00
Jinwoo-H 9e2da765fa feat(mobile): complete hybrid parity hardening 2026-08-23 20:08:01 -04:00
Jinwoo-H 2094dde1f9 test(mobile): harden hybrid parity bounds 2026-08-23 05:48:58 -04:00
Jinwoo-H 7815f3afb3 fix(mobile): restore hybrid cutover parity seams 2026-08-23 05:34:16 -04:00
Jinwoo-H 9b9c76222f Fix iOS host cache root boundary 2026-08-23 05:17:55 -04:00
Jinwoo-H 611428c9d5 Merge remote-tracking branch 'origin/main' into mobile-rearch
# Conflicts:
#	config/reliability-gates.jsonc
#	mobile/app/h/[hostId]/index.tsx
#	mobile/app/h/[hostId]/session/[worktreeId].tsx
#	mobile/app/h/[hostId]/tasks.tsx
#	mobile/app/index.tsx
#	mobile/package.json
#	mobile/pnpm-lock.yaml
#	mobile/src/browser/MobileBrowserPane.tsx
#	mobile/src/components/NewWorktreeModal.test.tsx
#	mobile/src/components/NewWorktreeModal.tsx
#	mobile/src/components/pr-sidebar/PRChecksSection.tsx
#	mobile/src/components/pr-sidebar/PRConflictingFilesSection.tsx
#	mobile/src/components/pr-sidebar/PRSidebarHeader.tsx
#	mobile/src/files/mobile-file-preview-source.test.ts
#	mobile/src/session/QuickCommandsSheet.test.ts
#	mobile/src/session/QuickCommandsSheet.tsx
#	mobile/src/session/mobile-file-tap-open.ts
#	mobile/src/session/mobile-session-route-types.ts
#	mobile/src/session/mobile-terminal-tab-agent.ts
#	mobile/src/session/use-mobile-diff-review-comment-actions.ts
#	mobile/src/session/use-mobile-diff-review-controller.ts
#	mobile/src/session/use-mobile-diff-review-send-actions.ts
#	mobile/src/session/use-mobile-native-chat-controller.ts
#	mobile/src/session/use-mobile-native-chat-drafts.test.ts
#	mobile/src/session/use-mobile-native-chat-drafts.ts
#	mobile/src/session/use-mobile-native-chat-message-send.ts
#	mobile/src/session/use-mobile-session-tabs-reconciliation.ts
#	mobile/src/session/use-quick-commands.ts
#	mobile/src/tasks/smart-source-paste-intent.ts
#	mobile/src/terminal/terminal-path-tap.ts
#	mobile/src/transport/host-removal-lifecycle.ts
#	mobile/src/transport/rpc-client.ts
#	package.json
#	src/main/browser/agent-browser-bridge.test.ts
#	src/main/browser/browser-screencast-stream.ts
#	src/main/daemon/headless-emulator.ts
#	src/main/native-chat/transcript-file-version.ts
#	src/main/native-chat/transcript-incremental-reader.ts
#	src/main/native-chat/transcript-tail-reader.ts
#	src/main/native-chat/transcript-watch-engine.ts
#	src/main/providers/filesystem-provider-contract.ts
#	src/main/providers/ssh-filesystem-provider.ts
#	src/main/providers/types.ts
#	src/main/runtime/orca-runtime-files.test.ts
#	src/main/runtime/orca-runtime-files.ts
#	src/main/runtime/orca-runtime.ts
#	src/main/runtime/rpc/methods/files.ts
#	src/main/runtime/rpc/terminal-multiplex.test.ts
#	src/relay/fs-handler.ts
#	src/renderer/src/components/ui/dialog.tsx
#	src/shared/terminal-quick-commands.ts
2026-08-21 03:46:22 -04:00
Neil 77f23b013f refactor(shared): drop the shared/types barrel and import from the real modules (#14447)
#14397 split `shared/types.ts` into 46 per-domain modules but kept the path as
a re-export barrel so the import sites did not have to change. This removes
the barrel: every consumer now imports from the module that actually declares
the type, and `src/shared/types.ts` is deleted.

Barrels hide where a type lives, make every consumer look like it depends on
the whole domain, and let an unrelated edit invalidate a module that ~2,000
files transitively import.

2,323 import declarations across 2,321 files. Rewritten mechanically: each
specifier was resolved to an absolute path via the TypeScript AST and
recomputed, rather than string-substituted, so alias forms (`@/../../shared/
types`) and per-specifier `type` modifiers survive.

Four cases the mechanical pass had to handle, each found by a gate rather than
by reading the diff:

- Modules inside `src/shared` import the barrel as `./types`, not
  `shared/types`. A pre-filter on the latter string skipped 176 of them and
  left imports dangling at a deleted file, which surfaced as confusing
  `Property 'x' is optional in type 'Repo' but required in Pick<Repo, ...>`
  errors rather than "module not found".
- The barrel RENAMED one type on the way through
  (`WorkspaceSource as WorkspaceCreateTelemetrySource`), so the original name
  in the owning module has to be re-aliased at each consumer.
- Three test files put `;(globalThis as ...)` on the line after the import.
  TypeScript parses that `;` as the import statement's terminator, so
  replacing through `statement.getEnd()` deletes it and breaks ASI. The
  rewrite now stops at the module specifier.
- A file that already imported directly from a module got a SECOND import
  from it, because the barrel re-exported those same names — which trips
  `import/no-duplicates` under `--deny-warnings`. A post-pass merges
  declarations sharing a specifier and type-only-ness; the `import type` plus
  `import` pair from one module is left alone, since that form is allowed.

Splitting one barrel import into several genuinely adds lines, which pushed
`terminal-layout-pty-ownership.ts` to 301 counted lines: its 107-character
import must wrap, and neither local type collapses onto one line (101 and 116
characters). Rather than contort a type declaration to fit a line budget,
`collectLeafIds` and `pruneLeaves` move to `terminal-pane-layout-tree.ts` —
they are pure structural operations on the layout tree and independent of PTY
ownership. `visible-worktrees.ts` similarly loses its own mini-barrel
re-export of `isDefaultBranchWorkspace`, with the four real consumers
repointed at the declaring module. No `max-lines` bypass added.

Verified: cold `tsc --noEmit` green on node, cli, and web (buildinfo deleted
first — these projects are `composite: true` and reuse stale caches); the full
`pnpm lint` green, not just bare oxlint — the narrower local check is what let
the duplicate imports reach CI; max-lines ratchet OK at 344.
2026-08-13 22:48:24 -07:00
Jinwoo-H f7ef96c8c9 Merge remote-tracking branch 'origin/main' into mobile-rearch
# Conflicts:
#	.gitignore
#	mobile/app/h/[hostId]/session/[worktreeId].tsx
#	mobile/src/components/MobileRichMarkdownEditor.tsx
#	mobile/src/components/mobile-rich-markdown-editor-html.ts
#	mobile/src/components/pr-sidebar/MobilePrComposeForm.tsx
#	mobile/src/session/use-mobile-native-chat-message-send.ts
#	src/main/git/runner.ts
#	src/main/native-chat/transcript-tail-reader.ts
#	src/main/runtime/orca-runtime.ts
#	src/main/runtime/rpc/methods/hosted-review.test.ts
#	src/main/runtime/rpc/methods/hosted-review.ts
2026-08-12 16:37:00 -04:00
Jinwoo-H 4846ee9538 fix(ci): restore mobile rearchitecture validation 2026-08-09 19:24:05 -04:00
OrcaWin ce43d114be feat(mobile): cut over to hybrid workspace route 2026-08-09 18:35:02 -04:00
OrcaWin f480eb23c4 test(mobile): harden hosted Android touch activation 2026-08-09 18:35:02 -04:00
OrcaWin 5112aa837d test(mobile): stabilize hosted Android journey 2026-08-09 18:35:02 -04:00
OrcaWin 279a1ff68e test(mobile): complete hybrid adversarial validation 2026-08-09 18:35:02 -04:00
OrcaWin 158cd4a311 test(mobile): harden hosted terminal links 2026-08-09 18:35:01 -04:00
OrcaWin 352fc2e0cb test(mobile): validate hosted image metadata 2026-08-09 18:35:01 -04:00
OrcaWin 32fef856af test(mobile): validate hosted repository files 2026-08-09 18:35:01 -04:00
OrcaWin 00e443fef2 test(mobile): validate hosted adversarial content 2026-08-09 18:35:01 -04:00