|
| 1 | +# Drive portability audit beyond #2652 |
| 2 | + |
| 3 | +Audit base: `f5f1764c2` on `origin/main`, 11 September 2026. Scope: one |
| 4 | +external-drive development kit used sequentially on compatible Macs, following |
| 5 | +[PR #2652](https://github.com/copse-dev/agent-pane/pull/2652). That PR is a |
| 6 | +documentation proposal; its encryption, launchers and portability acceptance |
| 7 | +gates are not implemented by opening it. This audit leaves encryption to that |
| 8 | +work and identifies independently reviewable implementation slices. |
| 9 | + |
| 10 | +## Already present |
| 11 | + |
| 12 | +- `packages/store-kit/src/copse-paths.ts` centralizes profile, user-data, |
| 13 | + workspace, worktree and scratch paths under `COPSE_DIR`, with granular overrides. |
| 14 | +- Threads and per-project stores use stable IDs; moving the root does not require |
| 15 | + rewriting transcript text. Project repositories themselves are separate data. |
| 16 | +- `src/main/app-init.ts` resolves Electron user data before constructing stores. |
| 17 | + Set both `COPSE_DIR` and `COPSE_PANEL_USER_DATA` for a prepared kit: the latter |
| 18 | + bypasses automatic migration of a host's legacy profile. |
| 19 | +- Local provider routes already exist. A new model-provider protocol is not |
| 20 | + required to use a disk-hosted local model server. |
| 21 | + |
| 22 | +## Implemented independently |
| 23 | + |
| 24 | +### Build-cache relocation |
| 25 | + |
| 26 | +The cache PR makes `scripts/patch-dev-name.mts` and `scripts/fetch-gortex.mts` |
| 27 | +derive their default caches from `COPSE_DIR`, while retaining dedicated cache |
| 28 | +overrides. Relative links allow a checkout and its cache to move together. |
| 29 | +Canonical parent paths handle macOS path aliases; dangling Electron links are |
| 30 | +recognized with `lstat`, and gortex links can be repaired from a populated cache. |
| 31 | +Tests move an actual directory tree and run the gortex installer against a local |
| 32 | +fixture cache without a download. |
| 33 | + |
| 34 | +This does not relocate pnpm/Corepack/download caches, provide missing binaries, |
| 35 | +or make a host-linked Git worktree an independent repository. It does not depend |
| 36 | +on the launch-PATH PR or encryption. |
| 37 | + |
| 38 | +### Preserve the launcher's tool selection |
| 39 | + |
| 40 | +The launch-PATH PR adds the supported `COPSE_PRESERVE_PATH=1` opt-in: Electron |
| 41 | +does not augment the supplied PATH, availability probes do not prepend host |
| 42 | +paths, and Make does not activate host nvm. Ordinary launches retain their |
| 43 | +existing behavior. A kit launcher must supply its own complete PATH, including |
| 44 | +the system commands it needs. This does not replace `HOME` or relax sandbox or |
| 45 | +credential filtering rules. |
| 46 | + |
| 47 | +The scope is deterministic PATH handling at these entry points. An interactive |
| 48 | +shell, external agent, MCP configuration, hardcoded executable or an executable's |
| 49 | +own dependencies can still refer to the host. No UI/layout change is involved. |
| 50 | + |
| 51 | +## Remaining PRs, in dependency order |
| 52 | + |
| 53 | +| Proposed PR | Current evidence / problem | Acceptance gate | |
| 54 | +| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 55 | +| Portable-kit manifest, inventory and launch preflight | No kit manifest or launcher exists. `package.json` releases are OS/architecture specific and macOS requires 26.0. `Makefile`, `scripts/sync-dev.mts`, postinstall scripts and native modules require supporting tools. Experimental `scripts/tauri-shell.mts` has its own home-rooted cache. | A read-only report inventories app/tool/model versions, resolved executable/library/symlink paths, free space, granular overrides and paths outside the kit. Missing disk/profile/tools stop launch before creating stores or downloading anything. Both Macs pass from a clean launch environment. | |
| 56 | +| Structured project relocation and Git repair | Projects persist absolute paths (`src/shared/types/state.ts`). Worktree operations resolve Git's administrative directories (`src/main/services/worktree-manager.ts`); a Copse profile alone does not contain each project's Git objects. This investigation checkout itself is a linked worktree with its admin directory on the host. | Move the kit to a different mount path containing spaces; retain project/thread IDs, current edits and active checkout associations. Check `.git`, `commondir`, submodule links and object alternates. Use independent clones and repair linked worktrees; do not replace strings in historical chat. Back up and validate a structured migration before writing. | |
| 57 | +| Controlled integration and child-process environment | `src/main/services/mcp/mcp-registry.ts` reads host `.cursor/mcp.json`; skill/plugin discovery and Cursor/Claude adapters consult host homes. Terminal startup inherits `SHELL` and shell configuration. `Makefile` and app startup are only two of the environment entry points. | Prepared local MCP/skills/plugins and shell tools run on both Macs with host profiles absent. Disable automatic package downloads; isolate configuration/cache paths per tool. Preserve provider-secret stripping in `child-process-env.ts` and existing shell permissions. Hook changes must follow the binding hooks/feature-packs plan. | |
| 58 | +| Local-only operation policy | `resolve-agent-model.ts` can fall back to cloud models; `small-tasks-provider.ts` can fall back to the chat model. Update checks, model catalogs, external agents, web integrations and downloads are independent network users. | Explicitly route every enabled role locally; prevent cloud fallback and defer external refresh/download work while retaining localhost models, MCP and previews. Complete a real edit/test task with external networking disabled, including review and title generation. | |
| 59 | +| Profile writer guard and owned-service shutdown | `src/main/index.ts` uses Electron's local single-instance lock and bypasses it for ACP. Gortex PID validation in `semantic-index.ts` checks that a process command names gortex, not that it belongs to this profile/host/boot. Shutdown cleanup exists but is not an eject protocol. | Concurrent writers are rejected across supported entry points. A PID copied from Mac A must never authorize signaling an unrelated gortex on Mac B. Bind owned services to profile and process identity, recover stale locks carefully, flush writes and stop owned processes before reporting safe shutdown. Test interruption, unplug/reconnect and failed flush without overwriting state. | |
| 60 | +| Pinned offline toolchain/model bundle and updates | `COPSE_DIR` is profile relocation, not a software distribution. `make run` may install/build; native dependencies, Git helpers, browser binaries, model runtimes, compiler/SDK inputs and package caches are separate. Browser sessions also have OS-bound storage outside Copse's application cipher. | Prepare artifacts online, then cold-start packaged Copse and `make run` offline on both Macs. Execute Git/worktree, PTY, search, browser and real model/tool tasks. Restore dependencies and rebuild native modules offline in a disposable checkout. Audit non-system libraries and absolute shebangs. Verify forward recovery from an interrupted update; browser authentication needs its own explicit portability decision. | |
| 61 | + |
| 62 | +The manifest/preflight and process-ownership work can start without encryption. |
| 63 | +Project relocation and integration policy also have independent code boundaries, |
| 64 | +but need migrations or behavioral decisions beyond a small path fix. The full |
| 65 | +launcher should compose those contracts rather than claim the two implemented |
| 66 | +changes establish a portable environment. |
| 67 | + |
| 68 | +## Validation and limits |
| 69 | + |
| 70 | +The implementation PRs carry their own check results. No external drive was |
| 71 | +modified, no user profile was migrated, and no credentials were copied during |
| 72 | +this audit. No two-Mac/offline/native-runtime acceptance is claimed. |
| 73 | + |
| 74 | +The final release gate remains the sequential rehearsal in #2652: cold-start |
| 75 | +both packaged and development builds offline on each Mac, perform a real coding |
| 76 | +task, stop/flush/eject, change the mount point, continue the same project/thread |
| 77 | +on the second Mac, then return to the first. Preserve an independent backup. |
0 commit comments