Skip to content

[Feature] Sync OpenCode upstream v1.14.20 intake #92

@Astro-Han

Description

@Astro-Han

What task are we trying to do?

Sync PawWork's vendored OpenCode foundation from the completed upstream v1.4.11 cycle to the current upstream release tag v1.14.20. v1.14.20 is now the release anchor for this intake cycle. Keep post-v1.14.20 fixes as follow-up candidates unless a specific post-tag fix is proven to block macOS or Windows release work.

What changed since this issue was opened?

Updated 2026-04-22: upstream published v1.14.20 at 2026-04-21 19:07 UTC, tag commit 3175a3c618 (release: v1.14.20). The v1.14.19..v1.14.20 delta contains 41 commits. Several commits previously listed as post-v1.14.19 candidates are now release-tagged scope: 92c005866 fixes local dynamic import on Windows and Node by using file:// URLs; 3406f1874 adds the plugin SDK env type; 38e2f4cdd adds desktop webRequest CORS handling; 91468fe45 and febadc558 are UI primitive fixes. The delta also includes upstream app UI, TUI, console, web, docs, Nix, debug-server, and experimental HTTP API work that should not automatically enter PawWork's core sync scope.

What do we do today?

PawWork completed the previous upstream sync cycle at OpenCode v1.4.11 through scoped squash PRs against dev. Current verification on 2026-04-22 shows upstream now publishes v1.14.20. PawWork product packages such as packages/opencode, packages/app, and packages/desktop-electron are at 0.2.5, while upstream-tracked package surfaces such as packages/plugin, packages/function, packages/shared, packages/ui, and packages/sdk/js are now at 1.14.19 after PR #102. The full upstream tag range v1.4.11..v1.14.20 reports 149 commits in GitHub compare, but prior PawWork sync PRs have already landed part of that range. Decide remaining work by comparing current code state and behavior, not by upstream commit hash alone.

What would a good result look like?

Create a new upstream sync cycle that keeps PawWork's existing policy: use graft plus scoped squash merges, do not import upstream contributor history, and do not directly sync packages/app/src/{components,pages,styles,theme,i18n}/** because the PawWork app UI rewrite owns that layer. Treat the list below as the candidate intake scope, not literal git cherry-pick commands.

Candidate intake commits

Target release anchor: v1.14.20 commit 3175a3c618 (release: v1.14.20). Treat it as release/version evidence, not as a standalone code candidate.

Base status: PR #102 (refactor: sync opencode config schemas) has merged and should be treated as the landed base for config schema, effect-zod, OpenAPI metadata, and related type surfaces. If a later lane discovers more base-owned generated/version/dependency work, stop and move it into a small base repair PR before widening that lane.

High-value runtime/session commits: 6f5a3d30f keeps recent turns during session compaction; aa86fb75a refactors compaction tail selection; 9819eb046 changes compaction prune from default-on to explicit opt-in and must be evaluated as part of the prune default sequence; 42771c1db budgets retained tail with media; 6eddf0824 flips toolcall prune defaults; b9640fc7e fixes the compaction prune test to explicitly enable the prune config option; c6c56ac2c renames tail_tokens to preserve_recent_tokens across config, compaction tests, SDK, and OpenAPI; 05cdb7c10 tags session unions and exhaustively matches events, including interleaved tool events, synthetic events, and compaction events; 11cd4fb63 extracts session entry stepping logic; 882b8e1e7 tracks retry attempts with detailed error context on assistant entries; 7a568a457 defers MessageV2.Assistant.shape access to break a compiled-binary circular dependency. Also note that packages/opencode/src/session/system.ts had no upstream changes in the original v1.4.11..v1.14.19 scope, so PawWork persona injection should not be a default conflict concern unless a newer diff proves otherwise.

High-value runtime resource commits: 8bc4f91fd fixes parallel edits sometimes overriding each other; 889087c96 restores the native ripgrep backend; a7a85c94b fixes Windows managed ripgrep install behavior and bumps ripgrep to 15.1.0 for ARM64 support; 9918f389e detects attachment MIME from file contents; 9c16bd1e3 makes skill logic more token efficient; 81b7b58a handles GitHub Copilot with Haiku where eager input streaming is not supported; 92c005866 fixes local dynamic import on Windows and Node by using file:// URLs and should move from follow-up to the Runtime Resource lane because it directly affects Windows plugin/tool loading.

NPM/plugin install commits: 1ee712e54 fixes the missing-node_modules package install path so it does not continue into dirty-lock checks after install; f27eb8f09 avoids reinstalling plugins too often by reusing the cached plugin install directory and resolving the entrypoint. Evaluate e539efe2b only behind a concrete gate: include it if PawWork's current Bun version reproduces or is confirmed to hit the upstream Arborist/Bun bug, or if the plugin install slice proves it is required. Do not include it merely to match upstream because it adds dependency, lockfile, shared type, and patch-file blast radius.

Config/schema/foundation commits likely needed as dependency chain: 289998481, 23f31475e, 2793502db, a6a4350d1, fc5b35314, 826fd3350, 5181f9b4e, 211136e3a, 7b98f544f, 36119ff17, bb90f3bbf, and 1fae784b8. Because PR #102 already landed, treat this list as historical context plus repair guidance, not as an open instruction to resync those commits from scratch.

Generated output policy: before each slice, decide whether generated files should be taken from upstream blobs or regenerated locally. Do not decide ad hoc inside each slice. If local regeneration is chosen, evaluate 357301991 (fix(generate): make openapi output deterministic by formatting in-place) first because it affects OpenAPI/SDK output stability. Generated chore: generate commits should be treated as part of their owning functional slice, not as independent product changes.

Desktop-electron commits to evaluate carefully: e543acf92 bumps Electron and fixes taskbar icon; b34ca44ab lazily loads electron-store to fix config directory selection; a546e88f3 runs JSON migration before spawning the sidecar; e5687d646 uses custom oc:// protocol for renderer windows; eb9906420 enables contextIsolation and sandbox; 38e2f4cdd adds CORS headers to the main window webRequest. These are important for PawWork's macOS and Windows desktop shell, but this lane needs an explicit design note or checklist before intake. The note should map upstream oc://, sandbox/contextIsolation, preload/IPC, electron-store config directory, icon/resource generation, and migration order to PawWork's current Electron shell. Do not take 38e2f4cdd alone without the related protocol/sandbox desktop changes.

Upstream app UI changes in v1.14.20: 16caaa2229, 22d33c57af, 224548d87d, 811a7e9a8b, and 8cc2c81d57 touch upstream app UI behavior such as sidebar avatar fallback, synced project updates, select-server layout, progress-bar setting, and prompt animation. Default skip direct file sync because PawWork's app rewrite owns packages/app/src/**. Only convert one into PawWork work if current PawWork behavior shows the same product issue and the fix can be expressed in PawWork's current UI architecture.

Provider/plugin/package commits: 3406f1874 adds an env parameter to WorkspaceAdaptor.create type; 5eaef6b75 avoids package.json drift during publish; 24fb9b129 stops release publish from rewriting dev, and should be evaluated with 5eaef6b75 if upstream publish plumbing stays in scope; release version commits such as 27db54c85, 7c6948cf6f, and 3175a3c618 are version evidence, not standalone product changes. Default skip 6e0178655 (NVIDIA provider catalog) unless PawWork explicitly chooses to add NVIDIA as a product/provider decision. Bedrock intake remains optional; if e2e7a8d72 and ce7923ada are included for current upstream Bedrock behavior, include the related 78ca49a1b Bedrock test fix as well.

UI primitive commits that are safe to evaluate because packages/ui is still synced from upstream: 91468fe45 uses parentID matching instead of positional scan for assistant messages; c0eab9e44 adjusts the UI tool diff sticky header offset in packages/ui/src/components/message-part.tsx; febadc558 corrects diff render condition logic. Do not apply upstream packages/app/src/** UI changes into PawWork's app rewrite.

TUI policy: PawWork does not keep a TUI product surface. TUI product commits should default to skip. TUI compatibility or tests may be included only when needed to keep shared runtime/session surfaces compiling or tested, or when a slice proves a TUI file is still part of a live package script or import chain. Do not assume PR #73 means all future upstream TUI features remain in scope. e95474df05 fixes an upstream TUI system-theme regression and adjusts OpenTUI dependency pins; keep it skip-by-default unless a selected runtime/package slice proves the dependency pin change is needed.

New optional or skip-by-default v1.14.20 candidates: 96a534d8c6 adds GET /config to the experimental HTTP API; include only if PawWork desktop/app needs it or if it is required by a selected runtime/API slice. debcff2b6b adds a debug workspace server and remains developer tooling, so skip unless we explicitly want that debug workflow. 2486621ca1 removes an unused upstream tool; include only if PawWork's current tool registry still carries that tool and the removal is proven safe with tests. b5acc2203c fixes permission routing for remote workspaces; evaluate only if PawWork keeps that shared permission path live outside TUI. ae7a3518f7, ad65af28e7, f74a255ca9, 6278ce51ce, and related generated commits are console/Zen routing work; skip by default because PawWork's core sync does not include upstream console/web/go surfaces.

Optional or dependency-only commits

Evaluate 078d8a07c and 23a2d0128 only if PawWork keeps upstream OpenTelemetry surfaces in scope; they add resource attributes and standardize session telemetry attrs, but PawWork product analytics/crash reporting should remain a separate product decision.

Evaluate 471b9f4dc, 1dd257b76, 5fa167334, e6fd57165, and a5d99e7a3 only as dependency-chain commits or if they prevent concrete ambient-instance bugs while applying later changes. They move worktree, MCP, provider, file, LSP, and formatter code toward explicit InstanceState context, but they are mostly architecture cleanup.

Non-goals and carve-outs

Do not directly sync upstream packages/app/src/{components,pages,styles,theme,i18n}/**. Keep PawWork-only differences such as packages/opencode/src/tool/trash.ts, packages/opencode/test/tool/trash.test.ts, packages/opencode/src/session/prompt/pawwork-persona.txt, and packages/opencode/src/provider/models-snapshot.js unless a later review proves a specific change is required.

Do not preserve upstream commit history inside PawWork. The commit list above is for scope analysis and review planning only. Because prior PawWork sync work used squash merges, do not decide whether a candidate is already present by upstream commit hash alone; compare current code state or behavior when needed.

Suggested execution plan

This replaces the earlier 5-slice execution plan. Keep the candidate commit sections above as the analysis index, but execute through the landed base, three lanes, and one optional tail.

Phase 0 Base PR: mostly landed through PR #102. Own config schema, effect-zod, SDK/OpenAPI, package/version surfaces, generated output policy, and any dependency/lockfile changes that later lanes need. If a remaining task needs to change Base-owned surfaces, use a small base repair PR instead of hiding it inside a later lane.

Phase 1 Session lane: can start after Base. Own session runtime, v2 event matching, compaction behavior, and the compaction prune default/test sequence. Keep this lane internally coherent because the compaction commits depend on each other.

Phase 1 Runtime Resource lane: can start after Base and run in parallel with Session and Desktop. Own tool/file behavior, parallel edit safety, read/media MIME handling, ripgrep backend, Windows managed ripgrep install support, local dynamic import on Windows/Node, skill token efficiency, npm/plugin install behavior, plugin cache reuse, and missing-node_modules handling.

Phase 1 Desktop lane: can prepare the design note/checklist in parallel immediately, then implement after Base. Own Electron shell changes, oc://, sandbox/contextIsolation, preload/IPC, electron-store config directory, icon/resource generation, migration order, and macOS/Windows desktop smoke coverage.

Phase 2 Optional tail: open only if a concrete product or release decision accepts the work. This covers upstream packages/ui primitives, optional Bedrock, optional publish plumbing, selected app-UI behavior reimplemented in PawWork architecture, and explicitly chosen provider catalog changes. Default skip NVIDIA provider catalog. Keep this tail out of the core sync path unless it becomes a blocker.

Parallelization rule: Phase 1 lanes should branch from the Base PR result, not from stale dev, to avoid repeated generated/schema conflicts. If a lane discovers it needs to touch Base-owned files, stop and either move that change back into Base or re-scope the lane before continuing.

Verification notes

Before implementation, refresh upstream with git fetch --no-tags upstream and resolve the exact target refs again. After each slice, run focused tests for the touched package, then at minimum run the repo's normal lint/typecheck path for the touched surfaces. For desktop-electron changes, include macOS and Windows desktop smoke coverage because context isolation, sandbox, protocol, CORS handling, and migration order are startup and packaging risks on both platforms.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium priorityenhancementNew feature or requestupstreamTracked upstream or vendor behavior

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions