Skip to content

feat: upgrade OpenCode to 2.2.0 - #5

Draft
dtump wants to merge 5 commits into
mainfrom
feature/opencode-v2-upgrade
Draft

dtump wants to merge 5 commits into
mainfrom
feature/opencode-v2-upgrade

Conversation

@dtump

@dtump dtump commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner

Important

DRAFT — do not merge yet. OpenCode 2.x needs to stabilize first. This PR is parked until the validation checklist below passes. The project stays on 1.x (main) in the meantime.

What

Upgrades the image from OpenCode 1.x (opencode-ai@1.18.16) to OpenCode 2.2.0. OpenCode 2.x is published as @opencode/cli — opencode-ai is frozen at 1.x — so the Dockerfile install and the update_pins.py tool registry switch package names. The --ignore-scripts + explicit postinstall.mjs install pattern is unchanged (v2 package has the same shape; postinstall re-reviewed per the Dockerfile's standing note).

Changes

  • Dockerfile / update_pins.py: opencode-ai → @opencode/cli; pin OPENCODE_VERSION=2.2.0
  • Drop OPENCODE_EXPERIMENTAL_AGENT_TEAMS=1 (no such variable in OpenCode 1.x ≥ 1.19 or 2.x); keep OPENCODE_DISABLE_AUTOUPDATE=1 (still honoured in v2) and IS_SANDBOX=1 (legacy HOST_UID=0 net)
  • opencode --version now prints opencode v2.2.0 — CI pin-match assertion updated
  • entrypoint.sh: the /root chown walk also filters No such file or directory — OpenCode 2's background service keeps transient files (flock lock dirs, service.json, SQLite sidecars) on the shared volume, and a concurrent container's start can race their removal
  • Routine soak-gated refresh of the other pins (openspec 1.14.3, pnpm 11→12, uv 0.13.5, glab 1.124.0, awscli 2.38.4)
  • fix(ci): ignore hadolint DL3003 for the tmux source build — pre-existing failure (every main push red since 2026-08-10)
  • OpenSpec: new change upgrade-opencode-v2 (validated, synced, archived); its deltas rewrite host-config-parity + persistent-session-storage (still Claude-flavoured after the fork migration) to OpenCode 2 reality; six implemented-but-unfinished pre-rename changes archived without syncing their stale/superseded deltas

User impact

  • Seamless: config locations, opencode.docker.json seed, host config mounts, and wrapper flags (--auto, --continue, --session, …) are unchanged; a v1-schema opencode.json is accepted and normalised in memory; provider credentials carry over (v2 imports auth.json)
  • Breaking: v1 conversation history does not migrate (fresh SQLite DB; only credentials import); OpenCode 2 runs a per-user background service whose stale registration self-heals on the next run (verified)

Verified so far (on this branch)

  • Unit tests (56), npm audit signatures for @opencode/cli@2.2.0 + @fission-ai/openspec@1.14.3 + pnpm@12.15.0 (registry signatures + attestations), openspec validate (change + 8 specs)
  • Host: docker build + opencode --version → opencode v2.2.0, smoke cell (warm volume + settings seed), background-service stale-registration recovery against warm volumes
  • CI on this branch: MCVS-PR-validation green after conventional retitle; hadolint fixed; shellcheck/unit tests green

⚠️ Must be checked / validated before this is merged

  1. Upstream service stability — blocking. Reproduced in our container: constant "Restarting service…" from the managed background service. Root-caused in our logs to a registration-slot stampede — 18× managed service registration replaced; shutting down within ~85s, 19 serve --service spawns in one day. Upstream: [service]: managed service stalls, watchdog recovery loses sessions (404 "session not found"), restart stampede races the service slot (2.0.25 vs 2.0.26) anomalyco/opencode#54181 (open, severity:high — "managed service stalls, watchdog recovery loses sessions, restart stampede races the service slot"). Our trigger was concurrent containers sharing opencode-root, but the stall half of the issue can hit a single instance. Gate: wait for an upstream fix, or validate a single-instance 2.x session over several real workdays with zero restart loops.
  2. "tool bash is not available" errors. v2 renamed the bash tool to shell and ships no alias. Seen when prompt content references bash; also plausible as a model-prior effect (Mistral Large 4) because a custom agent's Markdown body replaces the built-in system prompt that names the tools (model-request.ts:110). Gate: sweep host config + workspace content for bash tool references; A/B built-in vs custom agent; confirm the errors stop.
  3. Related open upstream issues producing similar "tool not available" symptoms — re-test at merge time: #59993 (tool catalog empty after location reload), #51949 (agent reports no tools after auto-compaction), #60014 (code-mode catalog omits built-ins), #52054 (http_proxy without no_proxy loops), #55937 ($HOME watcher starves the event loop).
  4. Concurrent containers: v2's single-slot service registration races across containers sharing the volumes (the stampede above). Until #54181 is fixed upstream, validate the guidance: one container per volume set; --ephemeral for second sessions; --standalone as a per-run alternative.
  5. Re-pin at merge time: run uv run update_pins.py (no override) so the pin is the newest soaked 2.x — 2.2.0 soaks 2026-11-03, and by merge time a newer 2.x will likely be eligible. This also turns the CI soak audit green (it is red until then — the only expected red job on this branch).
  6. Full CI matrix green at merge time: the Docker build job (version smoke + 10-cell smoke matrix) is currently skipped while the soak audit is red; all jobs (Validate, Docker build, General, MCVS-PR-validation) must pass before merge.
  7. Host-side validation to re-run at merge time: docker build, opencode --version → opencode v2.2.x, the full smoke/smoke.sh matrix, the gh-proxy integration test (tests/gh-proxy-integration.sh), and a config-parity spot check (agents/commands/skills/AGENTS.md discovery + v1-schema seed normalisation).

Follow-ups (separate, intentionally not in this PR)

  • Spec modernisation for the remaining Claude-flavoured specs (cli-help, package-managers, external-cli-tools, multi-workspace-mounts) — recover coverage from the archived deltas
  • Check divergence from upstream schubergphilis/claude-docker
  • Cleanup: inert prompts/ + statusline-command.sh mounts, --resume help example (should be --continue)
  • 3 open manual verification tasks in 2 archived changes (openspec 3.3 — done; git-overlay 5.3 — pending a host run)
  • Upstream issues worth filing: tool-name repair/alias for model-emitted legacy names (bash→shell); custom-agent system prompt replacing the tool-listing prompt

dtump added 3 commits October 29, 2026 10:02
OpenCode 2.x is published as @opencode/cli (opencode-ai is frozen at
1.x), so the Dockerfile install and the update_pins.py tool registry
switch package names. The --ignore-scripts + explicit postinstall.mjs
install pattern is unchanged; the v2 postinstall was re-reviewed per
the Dockerfile's standing note (same per-arch optional-dep + version
verify + fallback flow).

- Pin OPENCODE_VERSION=2.2.0 (soak override; the audit job reports it
  as inside the 7-day soak until 2026-11-03)
- opencode --version now prints 'opencode v2.2.0' — update the CI
  pin-match assertion
- Drop OPENCODE_EXPERIMENTAL_AGENT_TEAMS (no such variable in
  OpenCode 1.x >= 1.19 or 2.x); keep OPENCODE_DISABLE_AUTOUPDATE
  (still honoured in v2) and IS_SANDBOX (legacy HOST_UID=0 net)
- entrypoint: also filter 'No such file or directory' in the /root
  chown walk — OpenCode 2's background service keeps transient files
  (flock lock dirs, service.json, SQLite sidecars) on the shared
  volume, and a concurrent container's start can race their removal
- Routine soak-gated refresh of the other pins (openspec, pnpm 11->12,
  uv, glab, awscli) from the same update_pins.py run

Verified: unit tests (47), npm audit signatures for @opencode/cli@2.2.0
(registry signatures + attestations), docker build + smoke cell on the
host, background-service stale-registration recovery.
- New change 'upgrade-opencode-v2' (proposal, design, tasks, deltas),
  validated, synced and archived. Its deltas rewrite the
  host-config-parity and persistent-session-storage specs, which still
  described Claude Code after the fork migration, to OpenCode 2 reality:
  config paths, opencode.docker.json seed, v1-schema acceptance, SQLite
  session store, background-service self-healing, v1 history
  non-migration, and concurrent-container chown tolerance.
- Archive the six implemented-but-unfinished pre-rename changes
  (--help, openspec CLI, --registry, --tfe, version pins, git-config
  overlay) without syncing their delta specs: those deltas are
  claude-flavoured and partly superseded by the gh-auth-proxy sidecar,
  so syncing them would write known-wrong requirements. Spec
  modernisation for the remaining stale specs is a separate follow-up.
- Two archived changes keep open tasks that need a host docker run
  (openspec 3.3; git-overlay 5.3) — manual verifications for the
  operator; consistent with two pre-existing archived changes.
…pgrade

PR #4 (update_pins rate-limit handling + pin refresh) landed on main
after this branch was created. Pins resolve to this branch's versions:
they are the newer 2026-10-29 refresh and carry the OpenCode 2.2.0 pin
this PR exists to ship.
@dtump dtump changed the title Upgrade OpenCode to 2.2.0 (v2 branch) feat: upgrade OpenCode to 2.2.0 Oct 29, 2026
dtump added 2 commits October 29, 2026 10:14
Pre-existing failure: the tmux source build's in-tree ./configure needs
the working directory set, so the Validate job's hadolint step
(failure-threshold: warning) has failed on every main push since the
tmux build landed on 2026-08-10. The layer resets to / before it ends,
so no later layer inherits the directory. Verified locally with
hadolint v2.12.0 + the repo config: rc=0 after the ignore.
Task 3.3 verified on the host: the wrapper launched against an empty
dir with an empty OPENCODE_DOCKER_CONFIG_DIR; openspec --help exited 0
and openspec --version printed the pinned 1.14.3. Zero host state
reached the container.
@dtump
dtump marked this pull request as draft October 29, 2026 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant