What task are you trying to do?
Keep PawWork's vendored copy of packages/opencode and shared infrastructure in lockstep with upstream anomalyco/opencode so we do not accumulate architectural drift. The foundation strategy is now stable: opencode remains the foundation until PawWork crosses 10K users. We do not have the team to fork the foundation; staying current is non-negotiable infrastructure work.
This issue tracks the first full sync cycle from our fork point (v1.4.6 area) to upstream v1.4.11, which contains 309 commits including namespace unwrap, zod -> Effect Schema migration, HttpApi route changes, and workspace control-plane refactors.
What do you do today?
We previously used a pinned vendor fork plus selective cherry-picks. That worked for one cycle but is no longer enough. Skipping the architectural migrations now would make every future cherry-pick pay import-path, schema-shape, and route-contract translation cost.
A second structural problem is history shape. Our initial commit bde4c3927 initial: based on OpenCode (MIT License) is an orphan snapshot import, not a normal fork. A naive merge against upstream creates hundreds of false add/add conflicts.
What would a good result look like?
After this issue closes:
packages/opencode and shared infrastructure reflect upstream v1.4.11 semantics
- UI rewrite carve-out paths stay on
HEAD and are still owned by #26
- PawWork history keeps only PawWork-authored commits, not upstream contributor history
- Future syncs can reuse the same graft + squash workflow with smaller marginal cost
- Phase 1 macOS GUI flows still work end to end
The workflow itself lives in docs/upstream-sync.md. This issue tracks live status and lane ownership, not the whole protocol.
Live status
| # |
Branch |
Status |
| 1 |
sync/setup |
done locally |
| 2 |
sync/opencode-tool |
merged as #31 |
| 3 |
sync/opencode-provider-plugin |
merged as #33 |
| 4 |
sync/opencode-provider-runtime-bridge |
merged as #34 |
| 5 |
sync/opencode-runtime-core |
merged as #36 |
| 6 |
sync/opencode-cli-core |
merged as #46 |
| 7 |
sync/opencode-tui-compat |
last; scope decided from live bun run typecheck output after PR 8 merges |
| 8 |
sync/opencode-session |
next main lane |
| 9a |
sync/opencode-foundation-tail |
merged as #48 |
| 9b |
sync/nonui-primitives |
merged as #49 |
| 9c |
sync/desktop-app |
merged as #47 |
Execution plan
- PR 8
sync/opencode-session is now the next main lane. It starts after PR 6 and PR 9a and does not depend on packages/app, packages/ui, or packages/desktop-electron.
- PR 7
sync/opencode-tui-compat stays last. Decide exact scope from live typecheck after PR 8. Do not assume a cheap path-only tsconfig exclude is a safe fallback.
- Any remaining branch should refresh from
dev before final push. If bun.lock moved, regenerate it with bun install; do not hand-merge lockfile diffs.
Lane ownership after PR 5
- PR 6
sync/opencode-cli-core: packages/opencode/src/cli/** excluding src/cli/cmd/tui/**, plus packages/opencode/test/cli/run.test.ts
- PR 9a
sync/opencode-foundation-tail: remaining opencode-internal non-session foundation, specifically src/{provider,plugin,control-plane,file,mcp,project}/**, src/index.ts, and matching tests under test/{provider,plugin,file,mcp,project}/**
- PR 9b
sync/nonui-primitives: packages/ui/**, packages/util/**, packages/plugin/**, packages/function/**, packages/sdk/**
- PR 9c
sync/desktop-app: packages/app/package.json, packages/app/src/{context,types}/**, packages/desktop-electron/**
The current live dev..v1.4.11 diff makes PR 6, PR 9a, PR 9b, and PR 9c file-disjoint. That disjointness is the reason this plan is faster. If a later refresh shows overlap, re-cut before editing instead of relying on spillover.
Which audience does this matter to most?
Both. The upstream fixes in v1.4.7 to v1.4.11 affect user-visible behavior, and the architectural sync is what keeps the foundation maintainable.
Acceptance criteria
After all remaining sync PRs merge:
Out of scope
- TUI / ghostty / Windows-specific UX as product surface
- UI rewrite itself, which belongs to #26
- Workspace remote / control-plane activation beyond the inert foundation needed for sync
- Telemetry activation; upstream OTel code may land inert, but product analytics decisions stay separate
Extra context
- Workflow doc:
docs/upstream-sync.md
- Cross-link: #26
docs/TODO.md upstream sync entry
What task are you trying to do?
Keep PawWork's vendored copy of
packages/opencodeand shared infrastructure in lockstep with upstreamanomalyco/opencodeso we do not accumulate architectural drift. The foundation strategy is now stable: opencode remains the foundation until PawWork crosses 10K users. We do not have the team to fork the foundation; staying current is non-negotiable infrastructure work.This issue tracks the first full sync cycle from our fork point (
v1.4.6area) to upstreamv1.4.11, which contains 309 commits including namespace unwrap, zod -> Effect Schema migration, HttpApi route changes, and workspace control-plane refactors.What do you do today?
We previously used a pinned vendor fork plus selective cherry-picks. That worked for one cycle but is no longer enough. Skipping the architectural migrations now would make every future cherry-pick pay import-path, schema-shape, and route-contract translation cost.
A second structural problem is history shape. Our initial commit
bde4c3927 initial: based on OpenCode (MIT License)is an orphan snapshot import, not a normal fork. A naive merge against upstream creates hundreds of false add/add conflicts.What would a good result look like?
After this issue closes:
packages/opencodeand shared infrastructure reflect upstreamv1.4.11semanticsHEADand are still owned by #26The workflow itself lives in
docs/upstream-sync.md. This issue tracks live status and lane ownership, not the whole protocol.Live status
sync/setupsync/opencode-toolsync/opencode-provider-pluginsync/opencode-provider-runtime-bridgesync/opencode-runtime-coresync/opencode-cli-coresync/opencode-tui-compatbun run typecheckoutput after PR 8 mergessync/opencode-sessionsync/opencode-foundation-tailsync/nonui-primitivessync/desktop-appExecution plan
sync/opencode-sessionis now the next main lane. It starts after PR 6 and PR 9a and does not depend onpackages/app,packages/ui, orpackages/desktop-electron.sync/opencode-tui-compatstays last. Decide exact scope from live typecheck after PR 8. Do not assume a cheap path-onlytsconfigexclude is a safe fallback.devbefore final push. Ifbun.lockmoved, regenerate it withbun install; do not hand-merge lockfile diffs.Lane ownership after PR 5
sync/opencode-cli-core:packages/opencode/src/cli/**excludingsrc/cli/cmd/tui/**, pluspackages/opencode/test/cli/run.test.tssync/opencode-foundation-tail: remaining opencode-internal non-session foundation, specificallysrc/{provider,plugin,control-plane,file,mcp,project}/**,src/index.ts, and matching tests undertest/{provider,plugin,file,mcp,project}/**sync/nonui-primitives:packages/ui/**,packages/util/**,packages/plugin/**,packages/function/**,packages/sdk/**sync/desktop-app:packages/app/package.json,packages/app/src/{context,types}/**,packages/desktop-electron/**The current live
dev..v1.4.11diff makes PR 6, PR 9a, PR 9b, and PR 9c file-disjoint. That disjointness is the reason this plan is faster. If a later refresh shows overlap, re-cut before editing instead of relying on spillover.Which audience does this matter to most?
Both. The upstream fixes in
v1.4.7tov1.4.11affect user-visible behavior, and the architectural sync is what keeps the foundation maintainable.Acceptance criteria
After all remaining sync PRs merge:
bun installcleanbun run buildforpackages/opencodesucceedsbun run typecheckpasses across shipped packagesgit replace -lreturns empty after final cleanupgit log devfor the sync windowpackages/app/src/{components,pages,styles,theme,i18n}Out of scope
Extra context
docs/upstream-sync.mddocs/TODO.mdupstream sync entry