Repository navigation
chase(t3): merge upstream main 4f651cb10 - #658
Merged
Merged
Conversation
…es (#19938) Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: Julius Marminge <[email protected]>
…#19701) Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: Julius Marminge <[email protected]>
… in a prompt (#19485) Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: Julius Marminge <[email protected]>
…300) Co-authored-by: Julius Marminge <[email protected]>
…9813) Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: dan <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: Julius Marminge <[email protected]>
… (#18552) Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
…ge (#18603) Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: Julius Marminge <[email protected]> Co-authored-by: Claude Fable 5.1 <[email protected]>
…#19154) Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: Julius Marminge <[email protected]>
…9936) Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: SAPHID <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: Julius Marminge <[email protected]>
…(#19706) Co-authored-by: Ronak Guliani <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
…ls (#20382) Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: Julius Marminge <[email protected]> Co-authored-by: Claude Fable 5.1 <[email protected]>
Co-authored-by: Julius Marminge <[email protected]>
…or screen (#20999) Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Joaquin Alfian <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
…ke turn (#19196) Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
…end (#20414) Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Julius Marminge <[email protected]>
goat-ci 39553882748 ran the full suites and found failures outside the merge's conflicted files. - Restore GOAT cloud reattach: upstream's starting-only guards skipped runs that were already running, and attach failures were settled by ordinary start-failure handling instead of the start service (ProviderTurnStartService, RunExecutionService). - Update retained GOAT tests and fixtures for upstream API changes: router and environment-thread mocks, LegendList offset measurement, connection diagnosis atoms, webhook-coalescing scheduler job, the expanded stall diagnostic, mobile back-navigation hook, and the shifted GOAT migration ids in MemorySyncService. - Muse replay fixtures send GOAT's merged runtime instructions. - Enable GOAT Connect only inside upstream's new relay telemetry test.
- ServerBrowser fixtures supply Playwright ConsoleMessage.args() and the page metrics desktop snapshots now read. - ACP nested fallback MCP calls report the goat server name. - pair.test.ts cleans up its IPv6 and Tailscale temp directories. - FleetConsole waits up to 15 s for the lazy console on a loaded runner.
This was referenced Oct 21, 2026
lidge-jun
added a commit
that referenced
this pull request
Oct 21, 2026
Protocol-stop success cases race the remote script's real two-second grace period on busy runners. Make their fixture termination explicit: a socket controller waits for readiness, sends real SIGTERM to the captured fixture PID, releases its exit barrier, and waits for process-exit EOF. The production stop script, ownership probes, and timeout defaults are unchanged. Keep all 20 existing cases and add one manager-level failure/recovery case. Without the controller, the process acknowledges SIGTERM but remains alive across the real deadline; the test asserts the exact timeout message and intact ownership files, then releases and verifies cleanup. Unrelated PID, external/busy/unknown runtime, disconnect/shutdown, and old-entry Node/shim assertions remain. Closes #651. Refs #487. Validation: - Baseline `f045007ed`: focused protocol-stop file, 20/20 passed. - Deterministic RED: disable only the signal controller while keeping the exit barrier; the existing disconnect/runtime-command case fails with `did not stop within 2 seconds`. Repeated with the same result. - GREEN before the dev refresh: 21/21 passed. Package typecheck and lint passed (existing unrelated lint warnings). - Merged current dev `2e5707d82` (#658); current head `127792f87546f6b5d982206f2858e0783c3cefa3`: focused file **21/21 passed**, 251.52 s, exit 0; package typecheck **exit 0**; package lint **exit 0**, five existing warnings outside changed files. Commands: from `packages/ssh`, `vp test run --config vite.config.ts --testTimeout 180000 src/tunnel.protocol-stop.test.ts` and `vp run typecheck`; from root, `vp lint --report-unused-disable-directives packages/ssh`. - #658 compared before editing: it does not change these protocol fixture files. No runnerProcess or replacement-lock changes in this lane. Residual / NOT RUN: #487's EADDRINUSE handoff remains: `reserveLoopbackPort()` closes its probe/claim sockets before the runtime binds. No Net.ts redesign, whole-package/repo-wide local tests, real SSH host/hardware, client UI, or merge. Native subprocess/socket proof only; Effect TestClock cannot control these shell/process waits. Hosted CI remains pending, not certified. Hosted CI on the exact head: [goat-ci run 39568217741](https://github.com/goat-si/goat/actions/runs/39568217741), event `pull_request`, attempt **1**. `goat-scope` job **119115614611** and `goat-screenshot-gate` **119115614840** succeeded. Queued: `goat-typecheck` **119116632677**, `goat-test-ssh` **119116632877**, `goat-check` **119116632909**, `goat-build` **119116632971**, `goat-test-desktop` **119116633408**. GOAT will watch pending checks; no merge authority. Model: gpt-6-astra (high). Harness: Codex through GOAT.
lidge-jun
added a commit
that referenced
this pull request
Oct 21, 2026
) Grok's background-bash replay could advance the continuation's debounce while later wake frames were still being handled. In the original CI failure this split the expected two runs into a third run left `running`; extending the idle deadline cannot complete that run. Wait on a per-replay Deferred acknowledged after Grok's native `turn_completed` handler, then advance TestClock. `await_thread_idle` now checks the projection and waits for persisted `run.updated` events from a cursor captured before that check. The existing 60-second failure guard and run/request diagnostics remain unchanged. All changes are confined to replay fixtures and test helpers. Closes #654 Validation on `7f4ca3cff01ed9f2725280f1b74e5fe5d881d341`, based on dev `2e5707d820055bd0d6822ac3204825e2c4771d0b` (includes #658): - Regression red → green: removing the completion wait fails `does not finish grok_background_bash while its wake response is still arriving` with virtual time `6002` instead of `3002`; restoring it passes. The regression holds the completion acknowledgement with Deferreds and observes the real persisted continuation run and armed debounce, without sleeps. - `vp test run apps/server/src/orchestration-v2/testkit/OrchestratorReplayFixtures.integration.test.ts -t 'grok_background_bash|preserves the ACP model-write'`: exit 0, 6 passed / 136 filtered. Preserves all 141 tests surviving #658 and adds one regression (142 total); no existing assertions removed. - `cd apps/server && ../../node_modules/.bin/tsc-rs --noEmit`: exit 0, no errors or warnings (existing suggestions remain). - Changed-file `vp lint --report-unused-disable-directives`: exit 0; one pre-existing unused `assertUserMessagesExclude` warning in `fixtures/shared.ts`. Changed-file `vp fmt --check` and `git diff --check`: exit 0. - Before rebasing onto #658, the replay fixture, recovery and restart-background-note files passed together: 3 files / 151 tests. This is old-base evidence, not current-head full-suite certification. Per the supervisor resource cap, full current-head replay/server verification is delegated to hosted goat-ci. - Live Grok service/hardware verification: NOT RUN. No production userdata, repo-wide local checks, merge, or guard bypass. Hosted goat-ci: [run 39570000685](https://github.com/goat-si/goat/actions/runs/39570000685), event `pull_request`, attempt 1, reported head `7f4ca3cff01ed9f2725280f1b74e5fe5d881d341`. Currently queued: `goat-scope` (job `119121501186`) and `goat-screenshot-gate` (job `119121501341`); the test matrix is not scheduled yet. This is pending evidence, not CI success. The workflow checkout SHA is not yet observed in job logs. GOAT watches the PR for completion/failures. The repository has no `ci:server` label, so this is the normal import-graph-scoped PR run. Model: gpt-6-astra (high). Harness: Codex in GOAT.
This was referenced Oct 21, 2026
lidge-jun
added a commit
that referenced
this pull request
Oct 21, 2026
) Three notes screens bailed out of React Compiler because of `try/finally`; Start work also hit an unsupported expression inside `try/catch`. This preserves cleanup and retry identity using compiler-supported control flow, then replaces the fixed mobile-memory CI list with the entire mobile `unit` and `react` projects. The full suite exposed two inherited release-check failures after #658: test fixtures expected `pingdotgg/t3code` URLs while production correctly used `goat-si/goat-releases`. The fixtures now expect GOAT's feed/API URLs. Production release behavior, compiler assertions, bailout allowlist and test assertions are unchanged. The PR changes 9 files. Closes #600 Current head: `a559b602a2de0e1361594000fafa2f8dadf6f214`. Includes dev `2e5707d820055bd0d6822ac3204825e2c4771d0b` through a normal merge, with no force push. Scope selection preserves #658's removal of obsolete scanner tests and still selects the full mobile task through mobile's workspace dependencies. Verification: - On the preceding head `18d2dde58`, compiler/storage/notes: **992 passed**; scope selection: **39 passed**; mobile typecheck, changed-file lint/format and `git diff --check`: exit 0. - That head's full mobile suite exposed the fixture mismatch: **2,692 passed / 2 failed**, no skipped tests. [Hosted job 119118564943](https://github.com/goat-si/goat/actions/runs/39568522936/job/119118564943) reproduced the same two failures on merge ref `f1375832342907928c7b05b0a7acf51284f8984d`. - The new commit changes only five expected URL literals in `environment-maintenance.test.ts`, plus formatter wrapping. `git diff --check`, the normal staged-format hook and the normal pre-push workflow guard passed. No guard was bypassed. - After the two local heavy lanes released their slots, `vp test run --root apps/mobile --config vite.config.ts src/features/settings/environment-maintenance.test.ts` passed **7/7 tests**, exit 0, in 1.66s on this head. This verifies the two previously failing URL cases without a full local suite. - **Current-head hosted verification pending:** [goat-ci run 39571859624](https://github.com/goat-si/goat/actions/runs/39571859624), event `pull_request`, head `a559b602a2de0e1361594000fafa2f8dadf6f214`. Previous results do not certify this head. GOAT watches the run. The original compiler regression was reproduced red before the repair. Rendered interaction tests cover conflict resolution, completion navigation, retry identity and ambiguous launches; added failure tests cover rejected save/launch cleanup without sleeps. The initial implementation received an independent static review. NOT RUN on the final URL-fixture commit: full local mobile suite, fresh typecheck, native iOS/Android and screenshots. The supervisor capped local heavy work at two lanes, so the final suite proof is delegated to hosted CI. jsdom tests with native mocks are not native-client certification. No intended UI, navigation, payload or persistence behavior changes. No PR merge performed. #600 stays open until the merge manager lands the verified PR. No changes to #514's migration stack, FleetConsole, Bot access policy, hygiene or Cua work. Model: GPT-6-Astra (high). Harness: Codex in GOAT.
This was referenced Oct 21, 2026
lidge-jun
added a commit
that referenced
this pull request
Oct 21, 2026
`dev` failed the export half of `vp run knip:check` after #658 with 172 unused exports and one duplicate. Keep private helpers private, remove unreferenced aliases/wrappers and the unmounted beta notice, and preserve the active service and UI paths. The full check now reports zero unused exports and zero duplicates. The source cleanup covers the 94 files in the fresh inventory; one related documentation paragraph also updates the removed default-health layer description. Imports, re-exports and namespace consumers were traced before removing exports; 84 files have only export-modifier changes (plus formatter line wrapping). No tests/assertions, knip configuration, dependencies, or CI scopes changed. #664's mobile/CI ownership is untouched. Both orchestration protocol names remain. `ORCHESTRATION_PROTOCOL_MIN_SERVED` is an independent `1001` floor while the current maximum is also `1001`, preserving today's wire behavior. Four intentional legacy constants retain symbol-level `@public` metadata: the iOS clipboard UTI consumed by `T3ComposerEditorModule.swift`, and the legacy checkpoint prefix, pre-refresh ref and ref root covered by the existing persisted-ref compatibility contract (D17 in the plan referenced by `legacyT3Names.ts`, plus the V1 namespace in `structure/server.md`). Their literal values remain unchanged. Other private package exports were assessed by actual consumers, not by export-map presence. Validation: - Full `vp run knip:check`: exit 0, 172 → 0 unused exports, 1 → 0 duplicates. - `vp exec tsc-rs --noEmit -p <package>/tsconfig.json`: exit 0 for contracts, shared, client-runtime, ssh, provider-cursor, server, desktop and web. - Existing compatibility tests: 9 files / 127 tests passed, exit 0. - Existing boot-service, MCP-session and goal-controller tests: 3 files / 83 tests passed, exit 0. - Existing theme and Nightly beta tests: 2 files / 22 tests passed, exit 0. - Changed-file `vp lint`: exit 0; five existing warnings in `Fallback.ts` and `ProviderTurnStartService.ts`. - Changed-file formatting and `git diff --check`: exit 0. - Read-only review of the ten non-mechanical files: PASS, no blockers. It flagged the obsolete default-health description in `docs/internals/agentic-k8s.md:671`; the parent corrected that paragraph after checking the retained default rescheduler and real health-layer wiring. NOT RUN locally: full repository test/typecheck/check, native mobile/desktop runtime suites. Hosted goat-ci provides the broader gates. No merge is requested from this lane. Source-verification head: `7291767efb4e447c8216012e0f60dc744d2c7b07`, based on dev `09e92d0e8b0eba99b3447399c86d81cca7567a00` after #658 and #662. Full knip and web typecheck were rerun successfully after the base refresh; range-diff confirms the cleanup patch is unchanged. A narrow Browser-panel smoke at the final head loaded the isolated local thread view without new console errors. The owned dev server was stopped afterward; no native runtime or broad browser suite is claimed.  Current publication head: `19a2b7927f7db26a0fdccc76225c72431907937b` adds only the source-consistency documentation correction. Normal staged-format and pre-push guards passed, with no bypass. New-head hosted CI is pending; run 39570664707 covers the preceding source head only. The parent watches the PR without occupying a local heavy slot. Source tests/knip were not repeated for the prose-only follow-up. Closes #627. Model: gpt-6-astra. Harness: Codex in GOAT.
lidge-jun
added a commit
that referenced
this pull request
Oct 21, 2026
…703) * feat(web): Boat cloud machines show the Boat logo and state in Fleet (#659) Boat cloud machines appeared in Fleet as generic SSH hosts. A stopped Boat machine looked exactly like an SSH host that had gone away: same cloud icon, the "Unreachable" ring, and an "Unreachable" alert in the console. Fleet now shows Boat machines with Boat's logo, the label "Boat", and Boat's own state. A stopped machine gets a solid stop square and reads "Stopped: Resume it in Settings → Connections → Cloud machines." Starting, stopping, and failed machines get their own labels. While Boat says a machine is running, its SSH connection state shows as before. The graph node, the console host rows and alerts, the per-machine thread list headers, and the selected-machine label all apply this. | Before | After (light) | After (dark) | | --- | --- | --- | |  |  |  | The screenshots use the dev-only demo at `/fleet?fleetDemo=heat`, which now includes one running and connected Boat machine and one stopped Boat machine that a dispatcher reported. **How it is identified.** `buildFleet` reads the server's `CloudMachine` record (`provider: "boat"`, `state`, `presence`) through the new `identifyBoatMachine` in `@goat/client-runtime/cloud-machines`. When no record describes a host, for example while a dispatcher's cloud machine list has not loaded, it falls back to the reserved `boat-` alias with the state unknown. That alias rule is now one helper, `hasCloudMachineAliasPrefix` in contracts. The four existing `startsWith("boat-")` checks in HubNodes, SSH host setup, and the desktop hub import use it too. It is case-insensitive like OpenSSH host matching, so HubNodes and the hub import now also refuse `BOAT-…` aliases; SSH host setup already did. Settings → Cloud machines takes its status text from the same helper, with unchanged wording. **Logo.** This is Boat's official logomark from https://boat.dev/brand/logomark-ocean.svg (`#263FA9`). Dark surfaces use the fill of Boat's own `logomark-wash.svg` (`#FEFEFE`). It is inlined in `Icons.tsx` beside the other third-party marks, with its two fills allowlisted the way Cursor's are. Source and trademark notice: `apps/web/src/components/BOAT-LOGO-NOTICE`, registered in `third-party-licenses.config.json`. The generated web manifest includes the notice. **Verification** - Unit: `vp test run` on client-runtime `cloudMachines.test.ts` and `state/fleet.test.ts`, plus web `fleetConnection.test.ts`, `fleetTelemetry.test.ts`, `CloudMachinesSettings.logic.test.ts`, and `hubNodesImport.logic.test.ts`: 77 passed. - Browser (Chromium): `FleetGraph`, `FleetConsole`, `FleetThreadList`, and `CloudMachinesSettings` browser tests: 12 passed. They include a new check that Boat nodes show the logo and state, that a stopped node gets the square and no away ring, and that the mark computes to `#263FA9` in light and `#FEFEFE` in dark. - Server: `HubNodes.test.ts`, `HubNodes.cloud.test.ts`, and `SshHostSetup.test.ts`: 77 passed. `third-party-licenses.test.ts`: 28 passed. - `vp run typecheck` passes for contracts, client-runtime, web, and server. `vp lint` and `vp fmt --check` pass on the changed files. - Checked by hand in the dev web app, in light and dark mode. Mobile has no cloud machine or Fleet host UI, so nothing changes there. The status helper lives in client-runtime so mobile can reuse it. Implemented by claude-opus-5-5 through the Codex harness in GOAT. * fix(server): Windows thread worktrees check out in seconds and survive slow hooks (#694) Creating a thread worktree on Windows sat on "Check out files — 100%" for minutes and then failed with `GitVcsDriver.createWorktree … Git command timed out` (#677). Measured on `mini` (Windows 11, Git 2.55, Defender real-time on), the file checkout itself takes 8 s, or 4 s with parallel workers. The time goes to this repository's `post-checkout` hook, which runs `pnpm install` *inside* `git worktree add` (5 m 5 s). Git has already printed 100%, so GOAT's fixed 300 s timeout killed the command, and the setup step GOAT runs afterwards would have installed the same dependencies again. | On mini, real repo | Before | After | | --- | --- | --- | | Thread launch (UI, new worktree) | 323.5 s inside `git worktree add`, fails at 300 s | Check out files 100% in 1.4 s, agent starting within seconds | | `createWorktree`, launch shape | — | 2.0–3.0 s, 7,803 files (`.repos/` left out) | | `createWorktree` with the installing hook running | timed out at 300 s, worktree lost | checkout done at ~5 s; hook silent for 2 min, so GOAT stops waiting and keeps the worktree (≈170–178 s) | **What changed** - **No double install.** Thread launches set `GOAT_WORKTREE_SETUP=0` when the project has a `runOnWorktreeCreate` script. GOAT runs that script itself, with its output in the launch view. - **Sparse worktrees.** A new `worktreeSparseExclude` project-file field (`goat.json`/`t3.json`) keeps listed directories out of new worktrees: `worktree add --no-checkout`, `sparse-checkout set --no-cone`, then `checkout -f --progress`. CI already checks out with the same patterns. `post-checkout` is then replayed through `git hook run` with the all-zero previous HEAD, so hooks still recognize a new worktree. Git older than 2.36 lacks `git hook run` and gets a full checkout. This repo sets `[".repos/"]` (21,835 of 29,726 files). `git sparse-checkout disable` brings them back, and `vpr sync:repos` does that by itself. AGENTS.md points agents at the main checkout's `.repos/`. - **Progress-aware timeout.** `git worktree add` and the checkout now fail only after 2 minutes **without output**. Any line counts as progress, a hook's included. The error gives elapsed time and the last line, e.g. `Git made no progress for 2m 0s and was stopped after 5m 24s. Last output: Updating files: 100% (29631/29631), done.` A stall after `post-checkout` started means the files are already written, so the worktree is kept and the checkout step shows a warning. A stall before that, such as in `reference-transaction`, rolls back as before. Launch failures from a stall are reported as `unknown` / `git_stalled` / retryable instead of `validation_error`. The checkout step shows when the repository's hook is running. - **Windows host preparation.** These run in the GOAT server on the Windows machine, so they apply to the local desktop and to SSH hosts alike. Before a worktree add, `core.fscache` and `core.longpaths` are set repo-locally when no config level sets them. `core.untrackedCache` stays off, because Scalar disables it on Windows. Parallel checkout defaults to 8 workers on Windows instead of one per core, since Git for Windows before 2.56 can crash with "stack smashing detected" on many-core machines. A background PowerShell probe (`Get-MpComputerStatus`, `Get-MpPreference`, `Get-Volume`) checks whether Defender scans the resolved worktree folder. The result rides `ServerConfig.worktreeCheckoutHealth` (forward-compatible optional) and is re-sent as a snapshot when the probe finishes or **Worktree location** changes. Settings → Connections then shows the exact `Add-MpPreference -ExclusionPath '<folder>'` command for an administrator PowerShell and the Dev Drive alternative. GOAT never changes Defender. Config loads never wait for PowerShell.  **Not covered / limits** - On Windows, a `post-checkout` hook that GOAT stops waiting for keeps running: Git Bash re-creates processes on exec, which detaches them from git's process tree, so `taskkill /T` cannot reach them (verified on mini). Thread launches of this repo skip that hook, so nothing races the setup step. - Exclusions are unreadable without administrator rights; the notice then says "may scan". A ReFS volume is reported as unknown (no warning), because whether it is a trusted Dev Drive is only readable from localized `fsutil` output. - Mobile shows no Defender notice; agents read the stall and sparse notes in the thread's setup steps. **Validation** - macOS: focused `vp test run` on gitStallTimeout, worktreeCheckout, WorktreeCheckoutHealth, GitVcsDriverCore, ThreadLaunchService, ws, sync-reference-repos: 7 files, 270 passed. Server, web and contracts `tsc-rs --noEmit`, targeted `vp lint` and `vp fmt --check` are clean. Red checks: stall reset disabled, post-checkout-only keep disabled, and hook-stall keep disabled each fail their tests. - Windows (mini, Git 2.55): the same files pass except 9 tests that fail identically at the base commit (SSH auth classification, pathspec-magic filenames, CRLF content under `core.autocrlf=true`). Every new test passes on Windows. - Live on mini: before/after timings above, the Defender probe ("scanning"), the Settings notice and copy button, and a full UI thread launch into a sparse worktree. - Independent review: four rounds with GPT-6.1-Sol; rounds 1–3 findings fixed, round 4 PASS. - Not run: `goat-ci`/repo-wide checks (CI owns them), a Defender-excluded folder (none exists on mini; settings left unchanged), mobile. Closes #677 Model and harness: claude-opus-5-5 via Codex in GOAT. * fix(ssh): SSH runtimes stay reachable, adopt lost ownership, and prune on macOS (#683) ## Problem On 2026-10-21 a desktop on nightly .205 connected to mac-studio, where GOAT's own .203 runtime was serving. Everything that followed came from four client-side gaps: - **GOAT's own runtime was treated as foreign.** On 10-20 the host's `~/.goat/ssh-launch/runtime` directory had been moved aside and .203 restarted by hand, so it had no launch records. Ownership came only from those records, so every client reported it as `external` and showed `update_blocked` ("A GOAT server that this app didn't start or cannot replace..."). The only way out was a manual SIGTERM. - **Status flickered and went stale.** Every `ensureEnvironment` call published `preparing / connecting` before checking whether its forward still answered, and agents call it before every remote tool. `goat_ssh_host_status` returns a `preparing` snapshot as-is, so agents saw a host that never settled. A forward to port 3774 also kept answering after .203 was replaced by .205 on the same port, so the reused attachment kept reporting .203, and a refresh intent kept from .203 could keep reporting `update_waiting` and retrying. - **Agents could not recover.** `goat_ssh_runtime_update` in `when_idle` mode, the mode that cannot interrupt work, required `environment:maintain`, which thread credentials never carry. The denial only said "needs a live environment:maintain grant". - **Runtimes piled up.** Cleanup required `/proc` and `flock`, so it never ran on macOS. mac-studio had 23 version directories (6.8 GB) plus stale `.staging-*` directories. Where cleanup did run, it kept every older build it could not order, which covers most dev builds. Separately, servers that the launch script starts in tests ignored their test worker's death, and nine `goat-test-*` servers from 10-20 were still running. ## What changes - **Ownership follows the server.** A live server this user runs as `~/.goat/runtime/goat/versions/<v>/goat serve --host 127.0.0.1 --port <p> --base-dir ~/.goat` is GOAT's managed runtime when it has no records. The probe reports `liveAdoptable`, and an owning launch holding the host replacement lock writes its identity, port, PID and `managed` marker, then verifies them as before. From then on it updates only through its own drain: busy servers keep serving and the refresh waits, and nothing is signalled. If its runner was lost too, the rollback runner is this app's runner pinned to the live version. Adoption is refused when any `ssh-launch/*/pid` names a live process (another server, an older client's per-client directory, or an ownership change in progress), during a drain, on Windows, and for any other command line. Those servers stay attach-only, as before. - **Status reflects the live server.** A caller reusing a forward that still answers no longer publishes `preparing`. A reconnect after a stale forward still does. Reusing a forward now also reads the descriptor's `serverVersion`. If the server behind the forward changed, the client reconnects and reads the live server, so `runtimeVersion` and every runtime decision follow what actually answers. A launch that attaches to the requested build drops any refresh intent kept from the older server, so an already updated host never reports or retries another update. - **Agents can update safely.** A live, writable GOAT thread may start `goat_ssh_runtime_update` in `when_idle` mode under the same check it already passes to request approval. That mode only drains an owned older runtime with nothing running, and never replaces a newer or foreign one. `goat_ssh_host_prepare` still needs `environment:maintain`. For a thread caller, its denial now adds that threads never hold that scope and points to Settings → Connections or `goat_ssh_runtime_update`. The shared denial text that other tools embed is unchanged. - **Pruning works on macOS and keeps one rollback build.** On macOS, `lsof` replaces `/proc` for the in-use check and a directory mutex replaces `flock`. Cleanup keeps the live, retained and requested versions plus one rollback build: the proven-older build installed most recently, which is the one the host ran before. Builds that are newer, or whose order against the live build is unknown, stay. Each ordering check starts `goat`, so a large backlog is pruned over several connections, oldest installs first, within the existing cleanup deadline. Staging and trash directories over an hour old are removed. The probation and rollback window (`run-t3.previous`) still blocks cleanup. - **Test servers die with their worker.** Fixture servers started by the launch script get `</dev/null`, so the existing stdin watch cannot fire for them. They now exit when the test worker recorded in `<fixture>/.test/owner-pid` is gone or the fixture directory is removed. This applies to both the protocol and runner-switch fixtures. ## Decisions - **Not stacked on #626 or #644.** #626 lets the runtime update itself when idle, and #644 extends that to Windows. Both change the server's own update schedule. This PR changes the client's ownership, status and cleanup paths that #626 relies on: an adopted runtime becomes eligible for #626's self-update, because its records now name it. The two touch `tunnel.ts` and the launch baseline in different places, and whichever lands second regenerates the `launch` field of `remote-runner-baseline.json`. - **The first-connection idle refresh is kept.** It already drains only an idle owned runtime, and a busy or frozen host defers with the old server attached. A host whose activity cannot be read answers `unknown` and is never drained. The incident's teardown came from misclassified ownership and status, and those are what this PR fixes. - **Request to refer to ADR-0016.** ADR-0016 is the agentic goals controller. The probation and rollback rules are ADR-0013 and ADR-0019, and cleanup still never runs during a rollback window. - **Leaked servers are fixed in the fixture.** No separate issue is filed. The nine already orphaned `goat-test-*` processes on mac-studio were left alone, because they were not started by this run. ## Tests - `tunnel.protocol-adoption.test.ts` (new, real launch script and fixture server): - An idle orphan is replaced through its drain and supervisor, with no `stop`. - A busy orphan is adopted, keeps serving and defers the refresh. - A plain attach adopts the orphan. - A secondary preparation writes no records. - A foreign command line stays `external` and is never drained. - Records naming another live process refuse adoption and leave everything unchanged. - `tunnel.runtime-status.test.ts`: - Status stays `ready` while an agent call's reuse check is held open on a `Deferred`. - A forward whose server was replaced on the same port reconnects once to the live build, with no upload, and then reuses the forward again. - `tunnel.runtime-cleanup.test.ts`: - Without `/proc` and `flock`, `lsof` protects a build in use and the directory mutex is released afterwards. - A failing `lsof` keeps everything. - Only the rollback build installed last survives among builds that cannot be ordered against each other. - Commit stamps still choose the rollback build. - Leftover staging and trash directories are removed by age. - `testParentLifetime.test.ts`: a server started with no stdin exits when its owner is SIGKILLed, and when its fixture directory is removed. - `SshHostSetup.test.ts`: - A thread can update `when_idle`, reauthorized live as `orchestration:read` only. - A read-only thread is refused. - `prepare` still needs `environment:maintain`, and the denial names `goat_ssh_runtime_update`. - Existing tests that encoded the old rules were updated: - Stale records from an earlier server now lead to adoption, without a signal. - The fixture's ownership-loss race now hands the port to a truly foreign command. - `remote-runner-baseline.json`: only the `launch` fields were regenerated. Runner bytes are unchanged. There are no sleeps in these tests. Milestones are `Deferred`s, process exit events and `TestClock`. Commands are listed in the final comment with their exit codes. Not run: a live adoption and update against a real remote host. That needs a published build containing this change. Model and harness: claude-opus-5-5 in GOAT through the Codex harness. * fix: keep unused implementation exports private (#672) `dev` failed the export half of `vp run knip:check` after #658 with 172 unused exports and one duplicate. Keep private helpers private, remove unreferenced aliases/wrappers and the unmounted beta notice, and preserve the active service and UI paths. The full check now reports zero unused exports and zero duplicates. The source cleanup covers the 94 files in the fresh inventory; one related documentation paragraph also updates the removed default-health layer description. Imports, re-exports and namespace consumers were traced before removing exports; 84 files have only export-modifier changes (plus formatter line wrapping). No tests/assertions, knip configuration, dependencies, or CI scopes changed. #664's mobile/CI ownership is untouched. Both orchestration protocol names remain. `ORCHESTRATION_PROTOCOL_MIN_SERVED` is an independent `1001` floor while the current maximum is also `1001`, preserving today's wire behavior. Four intentional legacy constants retain symbol-level `@public` metadata: the iOS clipboard UTI consumed by `T3ComposerEditorModule.swift`, and the legacy checkpoint prefix, pre-refresh ref and ref root covered by the existing persisted-ref compatibility contract (D17 in the plan referenced by `legacyT3Names.ts`, plus the V1 namespace in `structure/server.md`). Their literal values remain unchanged. Other private package exports were assessed by actual consumers, not by export-map presence. Validation: - Full `vp run knip:check`: exit 0, 172 → 0 unused exports, 1 → 0 duplicates. - `vp exec tsc-rs --noEmit -p <package>/tsconfig.json`: exit 0 for contracts, shared, client-runtime, ssh, provider-cursor, server, desktop and web. - Existing compatibility tests: 9 files / 127 tests passed, exit 0. - Existing boot-service, MCP-session and goal-controller tests: 3 files / 83 tests passed, exit 0. - Existing theme and Nightly beta tests: 2 files / 22 tests passed, exit 0. - Changed-file `vp lint`: exit 0; five existing warnings in `Fallback.ts` and `ProviderTurnStartService.ts`. - Changed-file formatting and `git diff --check`: exit 0. - Read-only review of the ten non-mechanical files: PASS, no blockers. It flagged the obsolete default-health description in `docs/internals/agentic-k8s.md:671`; the parent corrected that paragraph after checking the retained default rescheduler and real health-layer wiring. NOT RUN locally: full repository test/typecheck/check, native mobile/desktop runtime suites. Hosted goat-ci provides the broader gates. No merge is requested from this lane. Source-verification head: `7291767efb4e447c8216012e0f60dc744d2c7b07`, based on dev `09e92d0e8b0eba99b3447399c86d81cca7567a00` after #658 and #662. Full knip and web typecheck were rerun successfully after the base refresh; range-diff confirms the cleanup patch is unchanged. A narrow Browser-panel smoke at the final head loaded the isolated local thread view without new console errors. The owned dev server was stopped afterward; no native runtime or broad browser suite is claimed.  Current publication head: `19a2b7927f7db26a0fdccc76225c72431907937b` adds only the source-consistency documentation correction. Normal staged-format and pre-push guards passed, with no bypass. New-head hosted CI is pending; run 39570664707 covers the preceding source head only. The parent watches the PR without occupying a local heavy slot. Source tests/knip were not repeated for the prose-only follow-up. Closes #627. Model: gpt-6-astra. Harness: Codex in GOAT. * test(web): LocalApi test imports the module at collection (#706) On the EPYC runners, `apps/web/src/localApi.test.ts` "fails closed in a browser when no themed host is available" sometimes hits the 15 s test timeout and fails `goat-test`. On the same head it passed in 8.7 s (#626, job 119204309511) and timed out at 15 s (#626 job 119208586004, #674 job 119198732167, #676 job 119198464013). Nearly all of the test's time is its first `await import("./localApi")` inside the test body. That import pulls the contracts schemas through `clientPersistenceStorage`, and on the shared, loaded EPYC host it can take longer than the whole test budget. `localApi.ts` reads `window` only when its functions run, so the test now imports it once at collection. That cost is no longer counted against the test. The mocks move into `vi.hoisted` so the hoisted `vi.mock` factories can reach them, and `vi.resetModules()` goes because nothing re-imports the module. The assertion is unchanged, and no timeout was added or raised. Validation: `vp test run --project unit src/localApi.test.ts` in `apps/web`: 1/1 passed. `vp fmt` and `vp lint` on the file: clean. Model: claude-opus-5-5 via the Codex harness in GOAT. * fix: finish the internal export cleanup for knip (#709) After #672 landed, `vp run knip:check` still failed on dev `27a3aa8bd38e56bcc03b131f98c09c96cb3805a8` for two unused exports: `GOAT_BOT_RUNTIME_MODE` and `describeMachine`. Both are used only inside their defining modules. Remove their `export` keywords so the complete knip check passes. Validation: - `vp run knip:check`: before **exit 1** with the two exports; after **exit 0**, both stages executed without cache hits. - `ChannelBotRegistry.test.ts`: **7 passed**, exit 0. - `FleetGraph.browser.test.tsx` with the web Vite config and Chromium browser project: **4 passed**, exit 0. - Server and web scoped typechecks, two-file `vp lint`, and `git diff --check`: exit 0. - Repository consumer search confirms both symbols are module-local; the existing exported `fleetMachineSubtitle` remains the caller API. This is a two-keyword module-visibility change, with no rendered UI change. The maintainer screenshot waiver applies on that basis; runtime behavior is covered by the existing tests above. Hosted goat-ci for the new head is pending and will be recorded separately. The SSH facts timeouts on #672 are not reported as passing or fixed by this patch. Closes #627. Implemented with GPT-6-Astra through the Codex harness in GOAT. * test(ssh): legacy fact checks avoid redundant launches (#708) dev's goat-ci has been red since trusted runs moved to the EPYC runners (#688). `packages/ssh/src/tunnel.facts.test.ts` "SSH host facts" cases hit their 60-second limit: run 39592871443 on dev (goat-epyc-09), and the same cases on #693. Each failing legacy-record case did four full runtime launches. On the EPYC hosts that is slower than on hosted runners, so the cases ran past the deadline. The fix keeps the initial launch and the poisoned-record launch, then checks positive recovery and the cache hit with the read-only `prepareRemoteRuntime` probe. Launch and probe share the same `compat_fact` implementation, so every assertion is unchanged: executable key, positive fact content, retained runtime snapshot, skipped compatibility re-query. The timeout is unchanged, and no production SSH code changes. Validation: the whole file passes locally (16/16, about 132 s on macmini). The two originally failing cases pass on lidge, and the ssh package typecheck, lint and format pass. EPYC confirmation comes from this PR's goat-ci. Written by the goatclaw D1 lane (gpt-6.1-sol, Codex in GOAT) and published by the goatclaw program manager (claude-opus-5-5, Codex harness in GOAT). * test(ssh): SSH facts launches get headroom on the shared EPYC host (#702) Since #688 moved trusted goat-ci runs to the EPYC runners, `goat-test-ssh` fails on dev and on unrelated pull requests. The failures are in `packages/ssh/src/tunnel.facts.test.ts`: "ignores a pre-U2 … record", "unknown 0 - is re-asked", and "the first reconnect after an install … (age 60 s)" hit the 60 s per-case ceiling. These cases run two full launches through fake executables, so they take about 11 s on a hosted runner (dev run 39567660825) but 47-60 s on EPYC. All EPYC runners share one 192-core host (`neuralarcade`, load average 98-110 during these runs). The same tests passed at 53 s in #688's last run (job 119190437700, goat-epyc-23) and timed out at 60 s on dev 4d1f2e3 (job 119198130805, goat-epyc-09), #659 (job 119198713944, goat-epyc-01) and #672 (job 119198467114, goat-epyc-14). None of those changes touched SSH code. The fix raises the file's `LAUNCHES_TIMEOUT_MS` ceiling from 60 s to 180 s, with a comment giving the measured hosted and EPYC times. The same constant also bounds the readiness cleanup in the install-reconnect case, which waits on the same fixture node starts. No assertions change. Validation: this PR's goat-ci on EPYC (`goat-test-ssh`). No local run: the failure only shows up under the shared EPYC load. Model: claude-opus-5-5 via the Codex harness in GOAT. * test(server): make Windows test fixtures portable (#674) ## Problem On a Windows dev host, 52 `apps/server` tests from #557 and #588 fail on current `dev` (`2e5707d82`, after #658). Almost all of them are fixtures that assume POSIX paths, file names, or file modes. Linux CI is unaffected. ## Change The fixtures now match how the product behaves on Windows. Assertions and counts stay the same unless noted. - **Native paths.** storageCleanup joins its worktree and orphan paths with `Path`, which fixes 21 of its 22 cases. The MCP toolkit reads its transcript through `path.fromFileUrl` instead of `URL.pathname`. OpenCode2 builds expected attachment paths with `resolveAttachmentPath`. CodexAdapterV2's relative image href uses `/`, as Markdown requires. - **POSIX-only cases.** worktreesDirectory injects the POSIX `Path` for the `/d/…` and mount-container cases. The OpenCodex Home test uses a native cwd and catalog path, matching what OpenCodex provides on Windows. - **Git and NTFS.** The fake ssh path in `GIT_SSH_COMMAND` is single-quoted so Git's `sh` keeps its backslashes. The same fix applies to the OS permission-error case, which only passed on Windows because ssh never ran. Hostile-name fixtures keep the names this host can store, using the new `@goat/shared/testing/fileNames` predicate beside `symlinksSupported`. On Windows, the pathspec-magic review case uses `[o]rdinary.ts`, which is still a pathspec: without literal handling it would select `ordinary.ts`. The trailing-space root case uses a no-break space, which Windows keeps and `trim()` still strips. storageCleanup replaces the worktree `.git` file instead of truncating it, because Git for Windows marks it hidden and Windows rejects the overwrite with `EPERM`. - **Narrow gates.** The sudo/`getent passwd` browser test skips on win32, since a passwd line cannot hold a drive-letter home. The Slack file-mode `0o600` assertions run only off Windows, which has no POSIX mode bits. channelReplica's real-script block runs only when a POSIX `sh` is on PATH; these scripts run on remote POSIX hosts over SSH. The GitVcsDriverCore CRLF case from #588 already passes on `dev` because `testUtils/gitConfig.setup.ts` sets `core.autocrlf=false`. The second #557 browser case no longer exists after #658. ## Not fixed: real runtime defect `DatabaseMaintenance > reports and deletes only the database from before 0.1.0` still fails with `EBUSY` / `LegacyDatabaseRemoveError`. It is a product bug, not a fixture problem. `removeLegacyDatabase` deletes `state.sqlite` while its own exclusive SQLite connection still holds the file open. POSIX allows unlinking an open file; Windows does not. As a result, deleting the database from before 0.1.0 always fails on Windows. Fixing it means changing how the lock is released before deletion without racing an old server, so it is left for a separate change. ## Scope and approval This covers the triaged issues #557 and #588. Closes #588. Refs #557, which stays open for the DatabaseMaintenance defect above. ## Verification All runs were live on Windows 11 (host `mini`, Node 24.16.0, Git 2.55.0.windows.3, system `core.autocrlf=true`). Each ran `vp test run` from `apps/server` on the 12 files listed in both issues. | Run | Result | | --- | --- | | Before, `dev` `2e5707d82` | EXIT 1: 52 failed, 605 passed, 3 skipped (660) | | After, all 12 files | EXIT 1: 1 failed (the DatabaseMaintenance defect), 647 passed, 12 skipped (660) | | After, the 11 files without DatabaseMaintenance | EXIT 0: 645 passed, 12 skipped (657) | | `channelReplica.test.ts` with Git's `usr\\bin` on PATH (live `sh`) | EXIT 0: 15/15 passed | Before the fix, 3 tests were skipped. The 9 new skips are the browser sudo case plus the 8 channelReplica script cases, which skip only because this host's PATH has no `sh`; the table's last row runs all 8 live. Typecheck (`vp run typecheck`) passes in `apps/server` and `packages/shared` (exit 0). `vp lint` passes on the changed files with exit 0; its three warnings are on unchanged lines. The POSIX-only cases (`/d/…`, mount containers, sudo/getent, file modes, newline and colon file names) still run unchanged on Linux and macOS, but I could not run them on those systems from this host. CI covers Linux. Model and harness: claude-opus-5-5 via Codex in GOAT. * fix(server): deleting the pre-0.1.0 database works on Windows (#682) ## Problem On Windows, `t3 doctor` cannot delete the database from before 0.1.0. `removeLegacyDatabase` took an exclusive SQLite lock on `state.sqlite` to make sure no old server was using it, then unlinked the file while that same connection still held it open. POSIX allows unlinking an open file. Windows refuses, so every removal failed with `EBUSY` and was reported as `LegacyDatabaseRemoveError`. `doctor` is the only caller; startup migration copies `state.sqlite` and never deletes it. ## Fix On Windows, the exclusive lock still proves that no other process has the file open. The connection then closes, and the files are deleted. Windows covers the gap between closing and deleting: SQLite opens its files without delete sharing, so if an old server opens the database in that window, the delete fails as busy and the database stays intact. A busy delete retries on a bounded exponential schedule (6 retries from 20 ms, about 1.3 s, for antivirus and indexers). If the file is still busy after that, the delete fails as `DatabaseInUseError`, the existing "stop GOAT first" error. macOS and Linux keep the old behavior: the lock is held through the delete. The platform comes from `HostProcess.Platform`, and the retry schedule can be injected through `layerWith`. ## Tests - The existing `reports and deletes only the database from before 0.1.0` case now passes live on Windows, with no skip and no changes to the test. - `releases its own lock before deleting` runs the Windows path on every platform. It uses a file system that refuses to delete a database any SQLite connection holds, as Windows does. When the code is changed to delete while still holding the lock, this test, the original case and the retry test all fail. - `retries a busy delete, then reports the database in use and keeps it` checks that a persistently busy file makes exactly 4 attempts, fails as `DatabaseInUseError`, and keeps the file. A file that is busy for two attempts is deleted. The test uses `TestClock` and has no sleeps. ## Verification All runs were live on Windows 11 (host `mini`, Node 24.16.0) with `vp test run` from `apps/server`: | Run | Result | | --- | --- | | `DatabaseMaintenance.test.ts`, `dev` `881757889` | EXIT 1: 1 failed (`EBUSY`), 2 passed | | `DatabaseMaintenance.test.ts`, this branch, 5 repeated runs | EXIT 0: 5/5 passed each time | | The 11 #557/#588 files on #674's head `717676302` (before) | EXIT 1: 1 failed, 651 passed, 4 skipped (656) | | The same 11 files on this branch merged with #674 (after) | EXIT 0: 0 failed, 654 passed, 4 skipped (658) | Both set runs had Git's `usr\bin` on PATH, so channelReplica's `sh` cases ran. The 4 skips are #674's win32 gates: browser.test.ts's only test (sudo/`getent`) and the symlink/POSIX cases in the Git driver tests. `vp run typecheck` exits 0 in `apps/server` and `packages/shared`, and `vp lint` and `vp fmt --check` pass on the changed files. Not run: macOS and Linux locally. Their path is the old code, and Linux CI covers it. #674 fixes the fixture failures in the other #557 files, and this PR fixes the remaining runtime defect. With both, every #557 case passes on Windows or is skipped on win32 as the issue proposes. Closes #557 Model and harness: claude-opus-5-5 via Codex in GOAT. * fix(ci): goat-ci gate jobs no longer queue behind the matrix on EPYC * ci: retrigger goat-ci
lidge-jun
added a commit
that referenced
this pull request
Oct 21, 2026
…#665) GOAT has no computer use. Upstream T3 Code has an open, unmerged Cua Driver stack by Julius Marminge (rebuilt from his #16527) that adds verified distribution, an opt‑in server lifecycle, an Electron host, and packaging, and attaches nothing to agents. This PR ports its server half, [pingdotgg/t3code#21694](pingdotgg/t3code#21694) at frozen head `b8569ac92` and [#21695](pingdotgg/t3code#21695) at `dc307c8a7`, pins Cua Driver 0.37.0, and forces the driver's telemetry and update check off. Computer use stays off by default (`enableCua: false`), and no provider or UI uses it yet. The first two commits are the upstream PRs applied as diffs, authored by Julius with the upstream commit list in each message. Desktop hosting and packaging follow in the stacked PR feat/cua-driver-desktop. ## GOAT deltas from upstream - **Pin 0.37.0** (upstream pins 0.34.1). `@trycua/cua-driver` on npm stops at 0.37.0, and the SDK and executable must share a version. Archive names, byte sizes and SHA‑256 come from the official `cua-driver-rs-v0.37.0` `SHA256SUMS` (re‑downloaded and compared). All six platform/arch entries match the downloaded archives and contain every required companion file. The 0.37.0 embedded host API is identical to 0.34.1's, so no ported logic changed. - **Telemetry and update check off at the daemon.** The host is built with `EmbeddedCuaDriverHost.withOptions(cuaDriverHostOptions(...))`, passing `CUA_DRIVER_RS_TELEMETRY_ENABLED=false`, `CUA_TELEMETRY_ENABLED=false` and `CUA_DRIVER_RS_UPDATE_CHECK=false`. The 0.37.0 host clears the daemon environment and **rejects** names outside its allowlist (`allowed_environment_name` in `cua-driver-sdk/src/embedded.rs`), so `DO_NOT_TRACK` and `CUA_TELEMETRY` cannot be passed there; trying makes host construction fail. This differs from plan D4's four‑variable list on purpose. - **Opt‑outs on the agent path.** The MCP descriptor that providers will spawn (`cua-driver mcp --embedded …`) is a separate driver process outside that allowlist, and upstream returns it with an empty environment. `CuaDriver.acquire` now adds all five opt‑outs (`withCuaDriverPrivacyEnvironment`), overriding any value the native descriptor carries. - **Renames** via `node scripts/goat-rename.ts --apply`: `@goat/*` imports, `GOAT_CUA_DRIVER_PATH`, `goat/cua/*` service keys, temp prefix. The standalone host identity is `si.goat.server` (upstream `com.t3tools.t3code.server`; `os-identities` keeps `com.t3tools` only for installed OS services). - **`server.ts`**: the runtime layer `pipe` already had 20 steps, its maximum, so `layerCuaDriver` joins the existing `ProjectStore`/`ThreadSearch` merge. Upstream's separate step fails typecheck in GOAT (TS2554). - **Merged with dev `881757889`** (after the upstream chase #658). `server.ts`, `packages/shared/package.json` and `third-party-licenses.config.json` take dev's versions plus this PR's additions. `pnpm-lock.yaml` differs from dev only in `@trycua`/`@ubjs` entries, and `vp i --frozen-lockfile` passes. - **Docs**: ADR‑0020 (`structure/decisions/ADR-0020-cua-driver-computer-use.md`), a "Computer use" section in `structure/server.md`, the shared export row, manifest and INDEX rows, and fork‑delta area `cua-driver` (`devlog/_chase/scan.sh --delta` ok). ## Verification Real macOS 26 (arm64), official 0.37.0 universal binary: - **Daemon env.** I started the host through the SDK using the shared options, with a hostile parent env (`CUA_DRIVER_RS_TELEMETRY_ENABLED=true`, `CUA_DRIVER_RS_UPDATE_CHECK=true`) and an isolated HOME. `ps -E` on the live daemon showed all three switches `=false` and `--host-bundle-id si.goat.server`. Under that env, `cua-driver telemetry status --json` reports `enabled: false, source: environment` (baseline without overrides: `enabled: true, source: default`). The isolated HOME held no installation ID or telemetry markers afterwards. 0.37.0's `get_config` does not report telemetry state, so this check relies on the process env plus `telemetry status`. - **Agent path.** I spawned the MCP proxy from the published descriptor: 62 tools listed over stdio (same count as upstream's Linux run), proxy env holds all five opt‑outs, and `telemetry status` under them reports `source: do_not_track`. - **Production standalone path.** `makeCuaDriverInstallation` + `FetchHttpClient` downloaded the 0.37.0 darwin archive from GitHub, verified size and SHA‑256, and published `tools/cua-driver/0.37.0` with exactly the five expected files in 1.6 s; cache reuse took 1 ms. `makeStandaloneHostFactory` with the real SDK then started and stopped the host. Upstream only qualified this path on Linux. This was a temporary test file, not committed. - `vp test run src/cua src/resourceTelemetry` (apps/server): 80/81. The one failure, `HostResources publishes load and disk`, is darwin‑only on dev: `diskPathForPlatform("darwin")` returns `$HOME` while the test expects `/`; neither file differs from dev, and CI runs Linux. `vp test run src/telemetry` (apps/desktop): 5/5. `vp test run src/settings src/resourceTelemetry` (packages/contracts): 198/198. - Red→green: emptying the host option environment fails `starts an explicit driver path with telemetry and update checks off`; restoring it passes. The existing lifecycle tests now assert the exact five‑variable descriptor, with a hostile `CUA_TELEMETRY=1` in the native fixture. - Typecheck exits 0 for apps/server, apps/desktop, packages/shared and packages/contracts (only pre‑existing Effect suggestions remain). Targeted `vp lint` and `vp fmt --check` pass on touched files; `server.ts:944` has a pre‑existing warning. ## Platform notes (re‑verified from 0.37.0) - **Windows UAC.** `cua-driver.exe` and `cua-driver-uia.exe` embed `requestedExecutionLevel level="asInvoker"`, so neither prompts on launch. `install.ps1` installs under `%LOCALAPPDATA%` without elevation and prompts only for its optional `-AutoStart` scheduled task, which GOAT never uses. Unelevated, the driver refuses elevated targets and may see truncated UWP/AppContainer UIA trees. Not run on a real Windows host (`win` was unreachable). - **Linux arm64.** Ships native aarch64 builds of the driver and SDK library (glibc ≥ 2.30, same floor as x64). The installer maps `Linux-aarch64`, and the release notes label all Linux builds "preview". A read‑only probe of an arm64 Ubuntu 24.04 host (glibc 2.39) found it compatible, but it is headless; I did not run the driver there. - **goat-ci** on head 5ef6fbc (after merging dev 10 commits past 8817578, including #661): [pull_request run 39591463869](https://github.com/goat-si/goat/actions/runs/39591463869) and [full dispatch run 39591455467](https://github.com/goat-si/goat/actions/runs/39591455467), both 18/18 jobs with goat-ci-result success. The previous head a1340bf was green on both runs (39574338635, 39574407950). ## Not run / open - Windows and Linux runtime with this pin, macOS TCC attribution, packaged desktop (next PR plus lane 3). No GUI capture or input was exercised. - The driver's `check_for_update` MCP tool still contacts GitHub when an agent calls it. Removing it belongs to the capability ceiling in the safety lane; ADR‑0020 records it as pending. - **Overlaps:** #661 edits `devlog/_chase/010_fork_delta.md` and goat‑rename rules (this adds one block in its own alphabetical slot; re‑run `goat-rename --check` after #661). #659 edits `third-party-licenses.config.json` (this keeps upstream's two Cua package overrides). #658 is the upstream chase; nothing here comes from upstream main. `structure/INDEX.md` already drifts from its manifest on dev (iMessage rows, two scopes); this PR adds only its own three rows. ## Review Independent read-only review by Codex gpt-6.1-sol. Round 1 returned MUST-FIX with three findings: unrelated lockfile peer re-resolution, docs describing the desktop host as current at this layer, and the ADR commit citation. All three are fixed in `8573ccbfb`. Round 2 returned PASS. Neither round found a runtime defect. Implementation: anthropic/claude-opus-5-5 via the Codex harness in GOAT (lane 1 of the Cua Driver program). Upstream implementation credit: Julius Marminge (pingdotgg/t3code #16527, #21694, #21695).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
GOAT dev was 522 upstream T3 Code commits behind
pingdotgg/t3codemain; the last sync was02b794c78(#562). This brings upstreammainin at4f651cb10(2026-10-21, #22649) with realgit mergecommits, so the merge-base moves to4f651cb10. The scan was pinned ate64766c56(#22613, 517 commits). Upstream then gained 5 commits during verification, including Electron 44.9.3 (#22645, which blocks compromised eMudhra CA keys), so the branch merges once more to4f651cb10. That second merge was conflict-free.Land with a merge commit, not a squash. A squash drops the upstream parents (devlog/_chase/README.md rule 1), and the next sync would replay these 522 commits.
bdd74b94dchase(t3): merge upstream main e64766c56, parentsf045007ed(dev) ande64766c56(upstream). All conflict resolution, migration shift, lockfile, lint backlog and test repairs6be7c3680194edc7dachase(t3): merge upstream main 4f651cb10, parents6be7c3680and4f651cb10(upstream). No conflicts39c83fb73t3code/*→goat/*(goat-rename --apply)121b130f74f651cb101e1d933f8ead908edbgoatMCP namespace for nested ACP calls, pair test temp cleanup, FleetConsole wait ceilingfeb2b7ddcV1ImportBoundary.test.tsandrpcInitialItems.memory.test.ts, which #22557 deleted;SOURCE_SCANNING_TESTSis now emptyUpstream commits: take / adapt / skip
This range is dominated by upstream's test cleanup: #22557 deleted 11k "low-signal" tests, followed by second passes #22588, #22589, #22591, #22592, #22593, #22599. That overlapped most GOAT-touched test files and pushed the trial merge to 1019 conflicting files.
goat/*and added togoat-rename'sLINT_RULE_IDS. Existing GOAT violations are tracked in backlogs (below). The 54 test-timing violations were fixed with Deferred/TestClock, except real-process and opt-in benchmark sites, which keep reasoned suppressionsEffect.fntracing)DesiredLinkReconcileServerBrowserDiagnosticsrecorderserverOwnership.tsspeaks GOAT (goat update,npx goat@latest) and also probes the owned legacy GOAT service unitgoat_process_group_*mode: "queue"sends steer in GOAT (#555), so "reports $label child results" follows the steer path, as on dev. The distinct/identical result-suppression assertions are keptConnectionEnvironmentsSectionandProviderInstallRowrelease-desktop.ymluses upstream's structure (Windows x64 built on Linux,verify_runnerjob) and keeps GOAT'sssh_runtime_bundle/mac_passkeysinputs and steps, so both callers stay validgoat/goat.cmdlaunchers. Without that it would delete runtimes still in use (red→green test)tunnel.test.tsexport pruning)packages/ssh/src/tunnel.tsstays GOAT; only the password/verification-code wording was portedMost useful for GOAT: webhook replay dedupe and coalescing #22234 and filters #22194; child model-option inheritance #16595; approval release for delegated waits #20037; orphan follow-up cancellation #22581; per-part connection diagnosis #22171; read-only rollback targets #21804; worktrees fetching their base branch's own remote #21032; EAS simulator device hosts #21844; Codex default effort #20991; SQLite checkpoint worker #21798 and #21799; Electron 44.9.3 #22645.
How conflicts were resolved
As in #562, the merge-base and upstream were first run through
scripts/goat-rename.ts --apply --rootin scratch worktrees. The 3-way merge against those renamed trees cut conflicts from 1019 files to 541 (about 1150 hunks; 464 both-modified, 75 deleted upstream but modified by GOAT). Eight lanes resolved the conflicts by area underdevlog/_chase/010_fork_delta.md.065_CodexUsageNativeTurnIndex,066_RepairClientSettlementTimestampsand067_WebhookDedupetake ids 65–67; GOAT's 065–091 move to 068–094 (files renamed, test ids and imports shifted).reconcileGoatMigrationIdsrelocates existing ledgers and runs the skipped 065–067. Those three run only where unrecorded and touch only upstream tables.GOAT_MIGRATION_NAMESis name-based and unchanged. A new test seeds today's released ledger (upstream ≤64, GOAT at 65–91): only 065–067 run, and a second run is a no-op. Older-ledger tests now also expect 065–067. Upstream un-exportedmigrationEntries; GOAT keeps the export for its ledger testsgoat_*names, registry descriptions, executable, service units and the Connect gatetunnel.tsstays GOAT;describeReadinessCauseexport restoredlucide-reactimports were swapped to Solar)pnpm-lock.yamlregenerated from GOAT's lockfile with pinned pnpm 11.10.0.[email protected](added by both sides) now carries GOAT's iOS permission lock and upstream's Android pre-draw layoutLint backlog
Upstream's
prefer-effect-fnand the webrequire-disposable-renderrule flag 738 pre-existing GOAT sites across 148 source files and 65 web test files. Following the jsdom-allowlist precedent (#514), the rootvite.config.tslists those files inPREFER_EFFECT_FN_BACKLOGandDISPOSABLE_RENDER_BACKLOG. Files leave a list as they are converted, and new code is still checked.GOAT bugs the merge exposed
apps/server/src/cloud/pinnedRuntime.ts: #22253's launcher scan looked only fort3launchers, so pruning could delete a runtime that a GOAT launcher still referenced. It now scans forgoatlaunchers (red→green verified).ProviderTurnStartService/RunExecutionService: upstream's new starting-only guards skipped cloud runs that were already running, and attach failures were settled as ordinary start failures. Already-running cloud tasks never reattached, and a failed attach could not leave the registered task link-only. GOAT'sexpectedStartStatusand attach-failure handoff are restored; the unchanged CloudRegisteredAttach, DevinCloud and Orchestrator control-read tests prove it.apps/server/src/cli/invocation.ts: runner commands picked packaget3even on GOAT installs. This was already broken on devf045007ed.@t3tools/contracts, whichgoat-renamemissed; they now import@goat/contracts.Workflows
Upstream edited
ci.yml,deploy-relay.yml,release-desktop.ymlandrelease.yml, and deletedcursor-hygiene-webhook.yml. All were alreadydisabled_manuallyon goat-si/goat. The pre-push guard accepted the push; nothing was bypassed.Verification
Canonical: full goat-ci dispatched on the branch head
feb2b7ddc, run 39563771647, success. All 17 jobs passed (check, typecheck, build, server 4/4 shards, web/packages, desktop, ssh, contracts, shared, client-runtime, mobile-memory, memory-growth) andgoat-ci-resultpassed. The logs contain no unhandled errors. Earlier runs on121b130f7(39553882748) and1e1d933f8(39556740096) failed and were fixed by the last three commits.Local (macOS):
vp lintreports 0 errors (warnings only), andvp fmt --checkis clean.goat-rename --applyrewrites 0 files on the branch.scan.sh --deltapasses (18 areas).f045007edserved as a baseline to separate merge regressions from existing failures.NOT RUN locally: full package suites outside the conflicted set (goat-ci covers them), builds, and live clients. No real SSH host, mobile device or desktop packaging was used.
Related: #633 (stacked on
test/514-5-decisions-sidebar-lib) edits the same jsdom allowlist area and will need a rebase after this lands; it was not taken over.Screenshots
This is an upstream merge. The web, mobile and desktop changes are upstream's own (each with screenshots in its upstream PR), plus GOAT re-applications that keep GOAT's UI, so no single before/after applies. A maintainer may need to apply
gui-screenshot-waivedforgoat-screenshot-gate.Done by claude-opus-5-5 in GOAT (Codex harness), with gpt-6.1-sol subagents through GOAT
delegate_task: 8 conflict lanes (server ×2, web ×2, mobile/desktop, contracts/client-runtime/shared, providers/ssh/scripts/docs, release workflow), plus follow-up lanes for out-of-lane ports, typecheck repair, lint and test repair.