Files
PaperClipAI/packages/adapters
DottaandClaude Opus 5.5 0252421d5c fix(opencode): isolate the native runner probe's OpenCode home (#19469)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Before a native OpenCode agent can run a task, agent setup runs a
harness test. The test sends one "Respond with hello." prompt through
`opencode run`.
> - The native OpenCode driver gives every OpenCode process its own
`HOME` and XDG data, cache, and state directories. The harness test did
not. It used the host user's `HOME`, so it shared
`~/.local/share/opencode/opencode.db` with every other OpenCode process
on the host.
> - OpenCode keeps one SQLite database for each data directory. When two
OpenCode processes start at the same time on one database, one process
can fail in about one second with `Error: Unexpected error / database is
locked`.
> - The harness test then reports `opencode_hello_probe_failed`. Three
failures pause agent verification, so the agent's first task stays
queued and never starts.
> - This pull request gives each local native harness test its own
temporary OpenCode home, the same as the native driver.
> - The benefit is that a native OpenCode agent passes setup when other
OpenCode processes run on the same host, and its first task starts.

## Linked Issues or Issue Description

No public issue exists. This is the bug description.

Refs #14393 (open, related): it isolates the OpenCode data directory for
the legacy `opencode_local` execution path. This pull request covers a
different path: the native runner harness test.

**What happened?**
Two native OpenCode runner end-to-end cells failed before any provider
turn and before their planned control-plane restart:
`stock-harness.runner-opencode.local.continuity-restart` ("Timed out
waiting for chat turn settles to waiting") and
`local-session-integrity.runner-opencode.local.structured-question-restart-resume`
("Timed out waiting for pending user question"). In both cells, the
server log shows `Agent lifecycle operation failed ... phase: verifying
... failureCode: harness_test_failed` three times. The run stayed
`queued` with `startedAt: null`. The second cell failed two attempts 2
seconds apart, which is shorter than one successful hello turn.

**Steps to reproduce**
1. Run several native OpenCode harness tests at the same time with the
host `HOME` (or run one while another OpenCode process starts).
2. Some `opencode run` processes exit 1 within about one second with
`database is locked`.
3. Agent verification records `harness_test_failed`, and after three
failures it pauses.

**Expected behavior**
The harness test uses an isolated OpenCode home, the same as the native
runtime that it qualifies. Other OpenCode processes on the host do not
affect it.

## What Changed

- `packages/adapters/opencode-local/src/server/test.ts`: for a local
`paperclip_runner` probe, create a temporary home and set `HOME`,
`XDG_DATA_HOME`, `XDG_CACHE_HOME`, and `XDG_STATE_HOME` inside it. Also
set `OPENCODE_DISABLE_MODELS_FETCH` and
`OPENCODE_DISABLE_DEFAULT_PLUGINS`, as the native driver does, so a
fresh cache does not fetch a catalog or install default plugins. Remove
the directory after the probe.
- The legacy `opencode_local` adapter keeps the host home, because its
`opencode auth login` credentials live there. Remote (sandbox) probes do
not change.
- `packages/adapters/opencode-local/src/server/test.remote.test.ts`: add
a regression for two concurrent native probes (each gets its own data
directory, and the directory is removed), and a sibling case that the
legacy adapter keeps the host home.

## Verification

- Red, unit: the new concurrent-probe test failed on the unfixed code
(`expected 'user' to match /^paperclip-opencode-native-probe-home-/`).
It passes with the fix. `cd packages/adapters/opencode-local && npx
vitest run src/server` gives 89/89 passed. `tsc --noEmit` passes.
- Red, real process: the unfixed `testEnvironment` against the real
pinned OpenCode 1.18.34 and OpenRouter, 12 concurrent probes, 3 rounds:
2 of 36 probes failed with `opencode_hello_probe_failed` (`database is
locked`). A plain shell reproduction with 6 concurrent `opencode run`
processes on the shared home: 2 of 6 failed with `database is locked`.
- Green, real process: the fixed `testEnvironment`, same 12 x 3 rounds:
36 of 36 passed with `opencode_hello_probe_passed`.
- End-to-end reruns of both failing cells: two rounds at this revision
with the real pinned OpenCode and OpenRouter (`pnpm test:e2e:runner --
--max-automatic-retries 0 --id <cell>`).
`stock-harness.runner-opencode.local.continuity-restart`: 2 of 2 passed.
`local-session-integrity.runner-opencode.local.structured-question-restart-resume`:
round 1 passed. Round 2 passed agent verification, asked the question,
and crossed the restart. After the user answered, the continuation run
failed with a different error: `runner_local_connect_failed: PRP command
run.attach timed out`. That failure is after the harness test and is not
changed by this pull request. It is tracked as a separate signature. In
all four reruns, agent verification passed on the first attempt.

## Risks

- Low risk. The change applies only to local native OpenCode harness
tests. The native runtime already uses an isolated home, so the test now
matches the runtime that it qualifies.
- A native probe no longer reads OpenCode credentials from the host
user's home. This is intended: native OpenCode agents receive provider
credentials through the agent environment, and the native driver does
not read the host home either.
- Each probe starts with a cold cache. With the catalog fetch and
default plugins disabled, a probe took 4 to 6 seconds in local tests,
the same as before.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, used through Claude
Code with tool use (shell, file edits, test execution).

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 09:27:13 -06:00
..