diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000000..6c76a2fe49a --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# Product source remains owned by its normal reviewers; localization inputs need focused review. +/src/renderer/src/i18n/locales/ @brennanb2025 +/config/scripts/*localization*.mjs @brennanb2025 +/config/scripts/*locale*.mjs @brennanb2025 +/i18next.config.ts @brennanb2025 diff --git a/.github/actions/install-node-dependencies/action.yml b/.github/actions/install-node-dependencies/action.yml index 0f3cba4107a..b23293e4a9a 100644 --- a/.github/actions/install-node-dependencies/action.yml +++ b/.github/actions/install-node-dependencies/action.yml @@ -6,6 +6,10 @@ inputs: description: Native runtime to prepare after the script-free install (none, node, or electron). required: false default: none + node-version: + description: Node.js version override; defaults to the version declared in package.json. + required: false + default: '' runs: using: composite @@ -17,11 +21,19 @@ runs: run_install: false - name: Setup Node.js + if: inputs.node-version == '' uses: actions/setup-node@v6 with: node-version-file: package.json cache: pnpm + - name: Setup requested Node.js + if: inputs.node-version != '' + uses: actions/setup-node@v6 + with: + node-version: ${{ inputs.node-version }} + cache: pnpm + - name: Validate native runtime shell: bash env: diff --git a/.github/workflows/computer-e2e.yml b/.github/workflows/computer-e2e.yml index 3023d414abe..29996c70361 100644 --- a/.github/workflows/computer-e2e.yml +++ b/.github/workflows/computer-e2e.yml @@ -9,6 +9,7 @@ on: - 'config/scripts/build-windows-cli-launcher.mjs' - 'config/scripts/build-windows-cli-launcher.test.mjs' - 'config/scripts/computer-e2e-workflow.test.mjs' + - 'config/scripts/computer-use-modifier-safety.test.mjs' - 'config/scripts/computer-use-skill-guidance.test.mjs' - 'config/scripts/computer-use-smoke.mjs' - 'config/scripts/computer-use-smoke.test.mjs' @@ -84,6 +85,7 @@ jobs: config/scripts/build-windows-cli-launcher.test.mjs src/main/ssh/ssh-remote-cli-launcher.test.ts config/scripts/computer-e2e-workflow.test.mjs + config/scripts/computer-use-modifier-safety.test.mjs config/scripts/computer-use-skill-guidance.test.mjs config/scripts/computer-use-smoke.test.mjs src/main/computer/computer-provider-lifecycle.test.ts diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index c2b597fafbf..2ab1ed44421 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -184,7 +184,9 @@ jobs: name: ssh docker watcher isolation needs: build runs-on: ubuntu-latest - timeout-minutes: 20 + # Why 35: the terminal parking + retention specs below add two more + # docker-rig tests capped at 240s each on top of the watcher isolation pair. + timeout-minutes: 35 steps: - name: Checkout @@ -227,6 +229,13 @@ jobs: - name: Run Docker SSH watcher isolation E2E run: xvfb-run --auto-servernum env SKIP_BUILD=1 ORCA_E2E_FORWARD_APP_LOGS=1 pnpm run test:e2e:ssh-docker-watcher-isolation + # Why always(): these specs gate the C1 terminal parking/retention budget + # over a real SSH host and run in no other lane, so a watcher-isolation + # failure above must not silently skip them. + - name: Run Docker SSH terminal parking + retention E2E + if: always() + run: xvfb-run --auto-servernum env SKIP_BUILD=1 ORCA_E2E_FORWARD_APP_LOGS=1 pnpm run test:e2e:ssh-docker-terminal-parking + - name: Upload watcher isolation traces if: failure() uses: actions/upload-artifact@v7 diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f5497280d23..4888dd6f3b3 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -62,6 +62,11 @@ jobs: - name: Verify localization catalog run: pnpm run verify:localization-catalog + # Why: extraction writes sorted evidence to an isolated temporary path, + # so feature PRs need one normalized AST pass rather than a three-OS matrix. + - name: Verify localization extraction + run: pnpm run verify:localization-extraction + - name: Verify localization coverage run: pnpm run verify:localization-coverage @@ -179,12 +184,14 @@ jobs: src/shared/posix-command-path-lookup.test.ts test: - name: tests ${{ matrix.shard }}/${{ strategy.job-total }} + name: tests node ${{ matrix.node }} ${{ matrix.shard }}/${{ matrix.shard_total }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: + node: ['24', '26'] shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + shard_total: [16] steps: - name: Checkout @@ -195,6 +202,7 @@ jobs: - uses: ./.github/actions/install-node-dependencies with: native-runtime: node + node-version: ${{ matrix.node }} - name: Install Electron package binary for tests run: node config/scripts/install-electron-package-binary.mjs @@ -208,7 +216,7 @@ jobs: --exclude=src/main/providers/__tests__/shell-ready-framework-example.test.ts \ --exclude=src/main/pty/omp-shell-wrapper.node-pty.test.ts \ --exclude=src/shared/posix-command-path-lookup.test.ts \ - --shard=${{ matrix.shard }}/${{ strategy.job-total }} + --shard=${{ matrix.shard }}/${{ matrix.shard_total }} package: name: package diff --git a/.github/workflows/terminal-ime-e2e.yml b/.github/workflows/terminal-ime-e2e.yml new file mode 100644 index 00000000000..7cef7d06cc5 --- /dev/null +++ b/.github/workflows/terminal-ime-e2e.yml @@ -0,0 +1,99 @@ +name: Terminal IME E2E + +on: + pull_request: + paths: + - '.github/workflows/terminal-ime-e2e.yml' + - 'config/patches/@xterm__xterm@6.1.0-beta.287.patch' + - 'config/scripts/run-terminal-ibus-hangul-e2e.mjs' + - 'config/scripts/terminal-ime-e2e-workflow.test.mjs' + - 'package.json' + - 'pnpm-lock.yaml' + - 'src/renderer/src/components/terminal-pane/keyboard-handlers.ts' + - 'src/renderer/src/components/terminal-pane/keyboard-handlers-ime.test.tsx' + - 'src/renderer/src/components/terminal-pane/pty-connection.ts' + - 'src/renderer/src/components/terminal-pane/pty-connection.test.ts' + - 'src/renderer/src/components/terminal-pane/terminal-ime-*' + - 'src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts' + - 'src/renderer/src/components/terminal-pane/xterm-bypass-policy.ts' + - 'src/renderer/src/components/terminal-pane/xterm-bypass-policy.test.ts' + - 'tests/e2e/chinese-ime-chat-input-repro.spec.ts' + - 'tests/e2e/korean-ime-terminal-shift-enter-commit.spec.ts' + - 'tests/e2e/terminal-ibus-hangul-native.spec.ts' + - 'tests/e2e/terminal-ime-*.ts' + workflow_dispatch: + schedule: + - cron: '30 9 * * *' + +permissions: + contents: read + +jobs: + linux-x11: + name: Linux X11 terminal IME + runs-on: ubuntu-22.04 + timeout-minutes: 25 + + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Install native build and IME tools + run: >- + sudo apt-get update && + sudo apt-get install -y + build-essential + dbus-x11 + dconf-gsettings-backend + ibus + ibus-hangul + libglib2.0-bin + python3 + xdotool + xfwm4 + xvfb + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version-file: package.json + + - name: Setup pnpm + uses: pnpm/action-setup@v6 + with: + run_install: false + + - name: Use external node-gyp to avoid pnpm bundled copy + run: | + npm install -g node-gyp@11.5.0 + echo "npm_config_node_gyp=$(npm root -g)/node-gyp/bin/node-gyp.js" >> "$GITHUB_ENV" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build Electron app for E2E + run: pnpm exec electron-vite build --mode e2e + + - name: Run deterministic terminal IME boundary tests + run: >- + xvfb-run --auto-servernum + env SKIP_BUILD=1 ORCA_E2E_FORWARD_APP_LOGS=1 + pnpm run test:e2e -- + tests/e2e/terminal-ime-exact-byte.spec.ts + --workers=1 + + - name: Run native IBus Hangul exact-byte tests + env: + SKIP_BUILD: '1' + run: pnpm run test:e2e:terminal-ime-native + + - name: Upload terminal IME evidence + if: always() + uses: actions/upload-artifact@v7 + with: + name: terminal-ime-evidence + path: test-results/ + retention-days: 7 + if-no-files-found: ignore diff --git a/.gitignore b/.gitignore index 00b6dd02894..7f954a8df11 100644 --- a/.gitignore +++ b/.gitignore @@ -44,9 +44,15 @@ package-lock.json *~ # OS +# Keep these in step with isOsMetadataSkillEntryName (skill-package-identity.ts): both disk +# walkers skip a plain file with one of these names, the git-tree producer does not, and +# ignoring them here is what keeps `git add -A` from committing a stray one. *.stackdump .DS_Store +._* Thumbs.db +ehthumbs.db +desktop.ini # Lint/cache .oxlintcache diff --git a/README.md b/README.md index b0ef0741e4b..cf4da325134 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Monitor and steer your agents from your phone — get notified when an agent finishes and send follow-ups from anywhere. -[iOS App Store](https://apps.apple.com/us/app/orca-ide/id6766130217) · [TestFlight](https://testflight.apple.com/join/YjeGMQBA) · [Android APK 0.0.32](https://github.com/stablyai/orca/releases/download/mobile-android-v0.0.32/app-release.apk) · [Docs →](https://www.onorca.dev/docs/mobile) +[iOS App Store](https://apps.apple.com/us/app/orca-ide/id6766130217) · [TestFlight](https://testflight.apple.com/join/YjeGMQBA) · [Android APK 0.0.36](https://github.com/stablyai/orca/releases/download/mobile-android-v0.0.36/app-release.apk) · [Docs →](https://www.onorca.dev/docs/mobile)