diff --git a/.github/workflows/cua-smoke.yml b/.github/workflows/cua-smoke.yml index 1e69359..4026e88 100644 --- a/.github/workflows/cua-smoke.yml +++ b/.github/workflows/cua-smoke.yml @@ -19,7 +19,9 @@ jobs: AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }} AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }} AZURE_OPENAI_API_VERSION: "2024-08-01-preview" - OPENCODE_URL: "http://100.108.64.76:4096" + # Android emulator reaches the runner host loopback via 10.0.2.2. + # A real `opencode serve` runs on the host (see steps below), making this a true E2E. + OPENCODE_URL: "http://10.0.2.2:4096" ARCHIVEBOX_URL: ${{ secrets.ARCHIVEBOX_URL }} ARCHIVEBOX_API_KEY: ${{ secrets.ARCHIVEBOX_API_KEY }} steps: @@ -67,6 +69,22 @@ jobs: - name: Install Python deps run: pip install openai + - name: Install & start opencode server on runner host + run: | + npm install -g opencode-ai + # Bind all interfaces so the emulator can reach it via 10.0.2.2. + nohup opencode serve --hostname 0.0.0.0 --port 4096 > /tmp/opencode-server.log 2>&1 & + echo "Waiting for opencode server /global/health ..." + for i in $(seq 1 60); do + if curl -sf http://127.0.0.1:4096/global/health > /dev/null; then + echo "opencode server healthy after ${i}s"; break + fi + sleep 1 + done + curl -sf http://127.0.0.1:4096/global/health || { + echo "::error::opencode server failed to become healthy"; cat /tmp/opencode-server.log; exit 1; + } + - name: Run CUA smoke test with emulator uses: reactivecircus/android-emulator-runner@v2 with: @@ -74,11 +92,20 @@ jobs: arch: x86_64 target: google_apis emulator-options: -no-window -no-audio -no-boot-anim -gpu swiftshader_indirect -no-snapshot + # NOTE: android-emulator-runner runs this script with /usr/bin/sh (dash). + # Avoid bash-only constructs like multi-line `|| { ... }` brace groups. script: | + # Non-fatal re-check; server health was already gated in the prior step. + curl -sf http://127.0.0.1:4096/global/health || echo "WARN: opencode health re-check failed (started in prior step)" adb install android/app/build/outputs/apk/release/app-release.apk adb shell am start -n cc.agentlabs.opencode/.MainActivity sleep 5 - python3 scripts/android-cua-smoke.py --model gpt-5.4 --include-xml + # True E2E: app connects to the local opencode server (10.0.2.2:4096) and verifies the session list. + python3 scripts/android-cua-smoke.py --model gpt-5.4 --include-xml --only-connect-scenario + + - name: opencode server log + if: always() + run: cat /tmp/opencode-server.log || true - name: Upload test artifacts if: always() diff --git a/.tasks/15/STATE.md b/.tasks/15/STATE.md new file mode 100644 index 0000000..35eb369 --- /dev/null +++ b/.tasks/15/STATE.md @@ -0,0 +1,30 @@ +# Task 15 — STATE +- phase: 3-design +- issue: #15 (CUA smoke can't reach opencode server in CI) +- branch: fix/cua-smoke-local-opencode-server +- supervisor: opus 4.8 (solo-founder loop) + +## Success metric (R1) +GitHub Actions `CUA Smoke Test` workflow run on the branch ends with +`All N scenarios passed.` (exit 0), where the connect-and-verify-sessions +scenario connected the app to a real opencode server running on the runner +and saw a non-empty session list. Observable in the Actions run log. + +## Approach +- Run real `opencode serve` on runner; app (emulator) reaches it via 10.0.2.2. +- Add `--only-connect-scenario` to smoke script; enhance connect goal to + create a session so a fresh empty server still yields a non-empty list. +- This also gives E2E verification for #10 (sessions list after connect). + +## Local de-risk (2026-06-01) +- opencode-ai@1.15.13 installs; `opencode serve` healthy in 1s. +- GET /global/health -> {"healthy":true}; /project/current 200; /path 200. +- POST /session then GET /session returns the created session. Flow validated. +- phase: 5-implemented, ready for CI verify. + +## CI verify round 1 (FAILED -> fixed) +- run 26750362939: build OK, opencode server step healthy, but emulator + script died with dash syntax error on `|| { ...; }` brace group before smoke ran. +- Fix 42e60db: emulator script: block runs under /usr/bin/sh; replaced brace + group with non-fatal one-line re-check. +- Re-dispatched: run 26751422570. diff --git a/README.md b/README.md index a0eda5e..4af50ea 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ OpenCode Mobile is a thin client. It speaks the opencode HTTP + SSE API: listing ## Supporters and Sponsors -OpenCode Mobile is built and maintained by [VIBE TECHNOLOGIES, LLC](https://www.vibebrowser.app/opencode). GitHub Sponsors help cover Sentry, EAS Build, and CI costs (~$60/month). The opencode Cloud hosted backend (planned, $10/mo) is the long-term revenue model. +OpenCode Mobile is built and maintained by [VIBE TECHNOLOGIES, LLC](https://agentlabs.cc/opencode). GitHub Sponsors help cover Sentry, EAS Build, and CI costs (~$60/month). The opencode Cloud hosted backend (planned, $10/mo) is the long-term revenue model. If OpenCode Mobile saves you time, consider sponsoring: @@ -134,7 +134,7 @@ If OpenCode Mobile saves you time, consider sponsoring: |---|---|---| | Supporter | $5/mo | Your name in `SUPPORTERS.md` | | Backer | $15/mo | Name + early access to opencode Cloud beta | -| Business | $50/mo | Logo on [agentlabs.cc/opencode](https://www.vibebrowser.app/opencode) + quarterly support call | +| Business | $50/mo | Logo on [agentlabs.cc/opencode](https://agentlabs.cc/opencode) + quarterly support call | Questions or private support: [support@vibebrowser.app](mailto:support@vibebrowser.app) diff --git a/app/(tabs)/settings.tsx b/app/(tabs)/settings.tsx index 6a2c549..f2d4d69 100644 --- a/app/(tabs)/settings.tsx +++ b/app/(tabs)/settings.tsx @@ -202,7 +202,7 @@ export default function SettingsScreen() { label="Privacy Policy" description="What data we collect and how" isDark={isDark} - onPress={() => Linking.openURL("https://www.vibebrowser.app/opencode-mobile/privacy")} + onPress={() => Linking.openURL("https://agentlabs.cc/opencode/privacy")} right={} /> diff --git a/distribution/app-store-listing.md b/distribution/app-store-listing.md index bfc351f..456652f 100644 --- a/distribution/app-store-listing.md +++ b/distribution/app-store-listing.md @@ -101,7 +101,7 @@ Alternative / supplemental terms to rotate in A/B: `code review`, `AI assistant` | Field | Value | |---|---| -| Support URL | https://www.vibebrowser.app/opencode | +| Support URL | https://agentlabs.cc/opencode | | Marketing URL | https://github.com/dzianisv/opencode-mobile | | Privacy Policy URL | https://opencode.vibebrowser.app/privacy | diff --git a/distribution/fdroid-submission/metadata.yml b/distribution/fdroid-submission/metadata.yml index 4c6a4d9..5c67d6d 100644 --- a/distribution/fdroid-submission/metadata.yml +++ b/distribution/fdroid-submission/metadata.yml @@ -21,7 +21,7 @@ License: MIT AuthorName: VIBE TECHNOLOGIES, LLC AuthorEmail: support@vibebrowser.app -WebSite: https://www.vibebrowser.app/opencode +WebSite: https://agentlabs.cc/opencode SourceCode: https://github.com/dzianisv/opencode-mobile IssueTracker: https://github.com/dzianisv/opencode-mobile/issues Changelog: https://github.com/dzianisv/opencode-mobile/releases diff --git a/distribution/ios-enrollment-runbook.md b/distribution/ios-enrollment-runbook.md index a6c093e..ad480f7 100644 --- a/distribution/ios-enrollment-runbook.md +++ b/distribution/ios-enrollment-runbook.md @@ -18,7 +18,7 @@ Reference: https://developer.apple.com/programs/enroll/ | Primary Contact / Authorized Agent | Dzianis Vashchuk | Governor of LLC | | Primary Contact Phone | (use a number reachable for Apple's verification call) | | | Primary Contact Email | support@vibebrowser.app | | -| Website | https://www.vibebrowser.app/opencode | | +| Website | https://agentlabs.cc/opencode | | --- @@ -62,7 +62,7 @@ Fill as follows: | ZIP | `98108` | | Country | `United States` | | Phone | (Dzianis's direct mobile — Apple calls this) | -| Website | `https://www.vibebrowser.app/opencode` | +| Website | `https://agentlabs.cc/opencode` | ### Step 4 — Verify Your Authority @@ -113,7 +113,7 @@ While waiting for Apple's verification call and approval: - [ ] Create app icon 1024×1024 PNG - [ ] Capture iPhone screenshots (use iOS Simulator in Xcode on any Mac) - [ ] Capture iPad screenshots -- [ ] Write/publish privacy policy at https://www.vibebrowser.app/opencode-mobile/privacy +- [ ] Write/publish privacy policy at https://agentlabs.cc/opencode/privacy - [ ] Set up EAS account at https://expo.dev/ (free tier, log in with Expo account) - [ ] Add iOS config patches to `app.json` (done in this PR) - [ ] Run `npx expo prebuild --platform ios` on a Mac to validate the Xcode project diff --git a/distribution/izzyondroid-submission/INCLUSION-REQUEST.md b/distribution/izzyondroid-submission/INCLUSION-REQUEST.md index 1f21083..c10a6d8 100644 --- a/distribution/izzyondroid-submission/INCLUSION-REQUEST.md +++ b/distribution/izzyondroid-submission/INCLUSION-REQUEST.md @@ -106,5 +106,5 @@ We will notify the IzzyOnDroid team via this issue when that happens. Developer: VIBE TECHNOLOGIES, LLC Email: support@vibebrowser.app -Website: https://www.vibebrowser.app/opencode +Website: https://agentlabs.cc/opencode Privacy policy: https://opencode.vibebrowser.app/privacy diff --git a/distribution/play-listing.md b/distribution/play-listing.md index 8ee5276..60211c5 100644 --- a/distribution/play-listing.md +++ b/distribution/play-listing.md @@ -114,7 +114,7 @@ Issues: github.com/dzianisv/opencode-mobile/issues | Tags | developer, ai, coding, open-source, productivity | Submit all five in Play Console. | | Email | support@vibebrowser.app | Already verified during signup. | | Phone | +1 360-504-8967 | Optional public; matches developer profile. | -| Website | https://www.vibebrowser.app/opencode | Already verified. | +| Website | https://agentlabs.cc/opencode | Already verified. | --- diff --git a/distribution/privacy-policy.md b/distribution/privacy-policy.md index 7d98255..3f2414f 100644 --- a/distribution/privacy-policy.md +++ b/distribution/privacy-policy.md @@ -106,7 +106,7 @@ All diagnostic data is transmitted over HTTPS (TLS 1.2+) to Sentry. We do not tr ## 10. Changes to This Policy If we make material changes to this policy, we will update the effective date and, where feasible, notify users via an in-app notice. The latest version is always available at: -https://www.vibebrowser.app/opencode-mobile/privacy +https://agentlabs.cc/opencode/privacy --- diff --git a/docs/security.md b/docs/security.md index d8cefe6..5699fbe 100644 --- a/docs/security.md +++ b/docs/security.md @@ -152,7 +152,7 @@ When the opencode AI agent requests a file-access permission, the notification b **Files:** `app.json:29`, `app.json:38-39` **Description:** Both platforms allow HTTP connections, which is required for local/LAN servers. This is intentional and correct for the use case. However, neither the Play Store listing, App Store listing, nor a privacy policy document currently explains that HTTP connections may be made to user-provided servers. Google Play's Data Safety section and Apple's App Privacy report will flag arbitrary network access if not documented. **Remediation:** -1. Update the privacy policy at `vibebrowser.app/opencode-mobile/privacy` to explain that the app connects to user-configured server addresses that may use HTTP. +1. Update the privacy policy at `agentlabs.cc/opencode/privacy` to explain that the app connects to user-configured server addresses that may use HTTP. 2. In Play Store Data Safety: disclose "Other app performance data" collected (crash reports via Sentry — opt-in). **Status:** Open diff --git a/scripts/android-cua-smoke.py b/scripts/android-cua-smoke.py index 20905d4..75215d9 100755 --- a/scripts/android-cua-smoke.py +++ b/scripts/android-cua-smoke.py @@ -603,8 +603,11 @@ def _connect_and_verify_sessions_goal(url: str) -> str: "Wait 3 seconds. " "Now navigate to the Sessions tab (bottom navigation bar). " "Wait 5 seconds for sessions to load. " + "If the sessions list is empty or shows 'No sessions yet', tap the '+' button " + "(top-right) to create a new session, wait 3 seconds, then navigate back to the " + "Sessions tab and wait 3 seconds for the list to refresh. " "Report SUCCESS if you see at least one session listed (a session title is visible). " - "Report FAILURE if the sessions list is empty, shows 'No sessions yet', or shows an error." + "Report FAILURE if the sessions list is still empty, shows 'No sessions yet', or shows an error." ) @@ -625,6 +628,12 @@ def main(): action="store_true", help="Skip the default connect-and-verify regression scenario.", ) + parser.add_argument( + "--only-connect-scenario", + action="store_true", + help="Run ONLY the connect-and-verify-sessions scenario. Use in CI with a " + "local opencode server for a deterministic true-E2E (no model backend needed).", + ) args = parser.parse_args() # Verify ADB @@ -635,15 +644,20 @@ def main(): except FileNotFoundError: sys.exit("adb not found in PATH") - scenarios = [{"name": "custom", "goal": args.goal}] if args.goal else list(SMOKE_SCENARIOS) + connect_url = args.opencode_url or os.environ.get("OPENCODE_URL") or "http://100.108.64.76:4096" + connect_scenario = { + "name": "connect_and_verify_sessions", + "goal": _connect_and_verify_sessions_goal(connect_url), + } - # Keep connect-and-verify in the default smoke path so regressions are exercised. - if not args.goal and not args.skip_connect_scenario: - connect_url = args.opencode_url or os.environ.get("OPENCODE_URL") or "http://100.108.64.76:4096" - scenarios.append({ - "name": "connect_and_verify_sessions", - "goal": _connect_and_verify_sessions_goal(connect_url), - }) + if args.only_connect_scenario: + # CI true-E2E: just connect to the local opencode server and verify the list. + scenarios = [connect_scenario] + else: + scenarios = [{"name": "custom", "goal": args.goal}] if args.goal else list(SMOKE_SCENARIOS) + # Keep connect-and-verify in the default smoke path so regressions are exercised. + if not args.goal and not args.skip_connect_scenario: + scenarios.append(connect_scenario) results = [] for scenario in scenarios: diff --git a/src/components/TelemetryConsentModal.tsx b/src/components/TelemetryConsentModal.tsx index b9f3d6f..28ed48e 100644 --- a/src/components/TelemetryConsentModal.tsx +++ b/src/components/TelemetryConsentModal.tsx @@ -46,7 +46,7 @@ export function TelemetryConsentModal({ visible, onAllow, onDecline }: Props) { {/* Privacy policy link */} Linking.openURL("https://www.vibebrowser.app/opencode-mobile/privacy")} + onPress={() => Linking.openURL("https://agentlabs.cc/opencode/privacy")} > Read our full privacy policy