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.
What task are we trying to do?
Sync PawWork's vendored OpenCode foundation from the completed upstream
v1.4.11cycle to the current upstream release tagv1.14.20.v1.14.20is now the release anchor for this intake cycle. Keep post-v1.14.20fixes 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.20at 2026-04-21 19:07 UTC, tag commit3175a3c618(release: v1.14.20). Thev1.14.19..v1.14.20delta contains 41 commits. Several commits previously listed as post-v1.14.19candidates are now release-tagged scope:92c005866fixes local dynamic import on Windows and Node by usingfile://URLs;3406f1874adds the plugin SDKenvtype;38e2f4cddadds desktop webRequest CORS handling;91468fe45andfebadc558are 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.11through scoped squash PRs againstdev. Current verification on 2026-04-22 shows upstream now publishesv1.14.20. PawWork product packages such aspackages/opencode,packages/app, andpackages/desktop-electronare at0.2.5, while upstream-tracked package surfaces such aspackages/plugin,packages/function,packages/shared,packages/ui, andpackages/sdk/jsare now at1.14.19after PR #102. The full upstream tag rangev1.4.11..v1.14.20reports 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 literalgit cherry-pickcommands.Candidate intake commits
Target release anchor:
v1.14.20commit3175a3c618(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:
6f5a3d30fkeeps recent turns during session compaction;aa86fb75arefactors compaction tail selection;9819eb046changes compaction prune from default-on to explicit opt-in and must be evaluated as part of the prune default sequence;42771c1dbbudgets retained tail with media;6eddf0824flips toolcall prune defaults;b9640fc7efixes the compaction prune test to explicitly enable the prune config option;c6c56ac2crenamestail_tokenstopreserve_recent_tokensacross config, compaction tests, SDK, and OpenAPI;05cdb7c10tags session unions and exhaustively matches events, including interleaved tool events, synthetic events, and compaction events;11cd4fb63extracts session entry stepping logic;882b8e1e7tracks retry attempts with detailed error context on assistant entries;7a568a457defersMessageV2.Assistant.shapeaccess to break a compiled-binary circular dependency. Also note thatpackages/opencode/src/session/system.tshad no upstream changes in the originalv1.4.11..v1.14.19scope, so PawWork persona injection should not be a default conflict concern unless a newer diff proves otherwise.High-value runtime resource commits:
8bc4f91fdfixes parallel edits sometimes overriding each other;889087c96restores the native ripgrep backend;a7a85c94bfixes Windows managed ripgrep install behavior and bumps ripgrep to15.1.0for ARM64 support;9918f389edetects attachment MIME from file contents;9c16bd1e3makes skill logic more token efficient;81b7b58ahandles GitHub Copilot with Haiku where eager input streaming is not supported;92c005866fixes local dynamic import on Windows and Node by usingfile://URLs and should move from follow-up to the Runtime Resource lane because it directly affects Windows plugin/tool loading.NPM/plugin install commits:
1ee712e54fixes the missing-node_modulespackage install path so it does not continue into dirty-lock checks after install;f27eb8f09avoids reinstalling plugins too often by reusing the cached plugin install directory and resolving the entrypoint. Evaluatee539efe2bonly 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, and1fae784b8. 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. Generatedchore: generatecommits should be treated as part of their owning functional slice, not as independent product changes.Desktop-electron commits to evaluate carefully:
e543acf92bumps Electron and fixes taskbar icon;b34ca44ablazily loads electron-store to fix config directory selection;a546e88f3runs JSON migration before spawning the sidecar;e5687d646uses customoc://protocol for renderer windows;eb9906420enablescontextIsolationand sandbox;38e2f4cddadds 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 upstreamoc://, sandbox/contextIsolation, preload/IPC, electron-store config directory, icon/resource generation, and migration order to PawWork's current Electron shell. Do not take38e2f4cddalone without the related protocol/sandbox desktop changes.Upstream app UI changes in
v1.14.20:16caaa2229,22d33c57af,224548d87d,811a7e9a8b, and8cc2c81d57touch 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 ownspackages/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:
3406f1874adds anenvparameter toWorkspaceAdaptor.createtype;5eaef6b75avoids package.json drift during publish;24fb9b129stops release publish from rewritingdev, and should be evaluated with5eaef6b75if upstream publish plumbing stays in scope; release version commits such as27db54c85,7c6948cf6f, and3175a3c618are version evidence, not standalone product changes. Default skip6e0178655(NVIDIA provider catalog) unless PawWork explicitly chooses to add NVIDIA as a product/provider decision. Bedrock intake remains optional; ife2e7a8d72andce7923adaare included for current upstream Bedrock behavior, include the related78ca49a1bBedrock test fix as well.UI primitive commits that are safe to evaluate because
packages/uiis still synced from upstream:91468fe45usesparentIDmatching instead of positional scan for assistant messages;c0eab9e44adjusts the UI tool diff sticky header offset inpackages/ui/src/components/message-part.tsx;febadc558corrects diff render condition logic. Do not apply upstreampackages/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.
e95474df05fixes 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.20candidates:96a534d8c6addsGET /configto the experimental HTTP API; include only if PawWork desktop/app needs it or if it is required by a selected runtime/API slice.debcff2b6badds a debug workspace server and remains developer tooling, so skip unless we explicitly want that debug workflow.2486621ca1removes an unused upstream tool; include only if PawWork's current tool registry still carries that tool and the removal is proven safe with tests.b5acc2203cfixes 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
078d8a07cand23a2d0128only 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, anda5d99e7a3only 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 explicitInstanceStatecontext, 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 aspackages/opencode/src/tool/trash.ts,packages/opencode/test/tool/trash.test.ts,packages/opencode/src/session/prompt/pawwork-persona.txt, andpackages/opencode/src/provider/models-snapshot.jsunless 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_moduleshandling.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/uiprimitives, 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 upstreamand 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.