Repository navigation
chore: sync swxtch with upstream anomalyco/opencode dev - #38
Conversation
Co-authored-by: frank <48937772+joe-ieta@users.noreply.github.com> Co-authored-by: kernel-oops <300539221+kernel-oops@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
Brings in 17 upstream commits (through 2406400). Merged rather than rebased: a rebase stopped on the first of our 16 commits and would have stopped again on #1 and #28, and it would have required force-pushing the default branch, rewriting 16 commits that 16 merged PRs reference. The conflict surface was small either way -- 5 files overlapped out of 108 ours and 84 theirs. Conflicts and how they were resolved: - packages/core/src/filesystem/search.ts -- took UPSTREAM's. Their anomalyco#50439 fixes the same import cycle our #2 did, independently and slightly more conservatively (it keeps `import type { FileSystem }` for the input types rather than de-namespacing them). Taking theirs keeps this file identical to upstream and removes a permanent source of rebase conflict. The other half of our #2, the layer-node walk guard, is not in upstream and is preserved; its tests still pass. - packages/core/src/npm.ts -- kept both import sets. One hunk, purely additive: `semver` from our #28 (compare requested versions, not just dependency names) and `createRequire`/`pathToFileURL` from upstream's anomalyco#50413 (resolve npm package entrypoint to a file under Node). The two fixes are unrelated and both survive; test/npm.test.ts auto-merged and its 19 tests pass. - bun.lock -- regenerated from the merged manifests. Verified: bun install --frozen-lockfile clean (satisfies the #33 gate), typecheck 30/30, core npm tests 19/19, layer-node tests 19/19, filesystem search tests 29/29. Claude-Session: https://claude.ai/code/session_017iG7xA9wRvNyFYZSXm8inU
|
Session stamp
|
The gate added in #22 ran `oxlint --config .oxlintrc.gate.json .` over the whole inherited tree. Its purpose is to catch bugs in what we write, but as built it policed code we merely inherit -- so upstream's choices could block every future sync. This sync is the first instance: 20 no-unreachable errors, 0 before the merge. They are not bugs. Upstream retires legacy console endpoints by inserting a throw at the top of the handler and leaving the old body in place: const user = Actor.assert("user") throw new Error("Go subscriptions have moved to the new Console") const { successUrl, cancelUrl, method } = input The rule is right and the code is deliberate. Fixing it in this fork would mean diverging on upstream-owned files and re-resolving it on every sync, which is the cost this gate exists to avoid paying elsewhere. Excludes packages/console/** -- which our 16 commits touch in 0 places -- and artifacts/**, which is scratch output rather than shipped source. No coverage of our own code is lost. Verified the gate still guards: injecting `throw` followed by a return into packages/opencode/src/cli/cmd/db-export-usage.ts is still reported as no-unreachable, and the tree is 0 errors once reverted. Claude-Session: https://claude.ai/code/session_017iG7xA9wRvNyFYZSXm8inU
CI caught a design flaw in the #22 correctness gateThe unit job failed on They are not bugs. Upstream retires legacy console endpoints by inserting a throw at the top of the handler and leaving the old body in place: const user = Actor.assert("user")
throw new Error("Go subscriptions have moved to the new Console")
const { successUrl, cancelUrl, method } = input // unreachable, deliberatelyAll 20 are that pattern, in The flaw is in what #22 shippedThat gate runs Fixed by scoping rather than weakening: The alternative — patching upstream's files to satisfy our lint — would mean diverging on upstream-owned code and re-resolving it on every sync. That is exactly the cost this fork is trying not to pay. Verified the gate still guardsInjected Still reported. Reverted, and the tree is |
packages/app/e2e is upstream's suite and this fork does not maintain it, so its flake should not block our feature work. #26 documents the known failure: the mock server has no v2 catalog routes, so every protocol:"v2" spec that boots a project runs against a crashed provider bootstrap, and review-line-comment fails all three attempts whenever timing lines up. Fixing that properly meant five files of divergence inside packages/app/e2e (see the closed #37). This fork already carries 62 CI/test-infrastructure files of divergence against 46 product files, which is the friction that makes every resync with upstream more expensive. One line in a workflow we already own entirely is the cheaper trade. The suite still runs and still uploads artifacts, so the signal is kept -- a failure now annotates the run instead of blocking it. Also updates the pinned test.yml::e2e digest in check-workflow-guards.ts, since changing the job necessarily changes it. The audit is green at 3/3. Claude-Session: https://claude.ai/code/session_017iG7xA9wRvNyFYZSXm8inU
CHANGESET.md at the root records both halves of what swxtch is: every upstream sync merged in, and every change the fork carries on top, each with its status against upstream. Backfilled from history: the fork base, the 2026-09-22 sync (#38) with its conflict resolutions, and the 20 fork changes since. It stays current mechanically rather than by memory: - sync-upstream.ts now merges with --no-commit and adds the sync's entry (range, commit count, conflicted files) inside the sync merge itself. On conflicts the entry is staged with the in-progress merge, and the conventional message goes to MERGE_MSG so the resolver's commit uses it. - script/changeset-check.ts fails a PR against swxtch with no `- **#<number>**` entry. Dependabot and generated sync-upstream-<timestamp> branches are exempt; a hand branch cannot opt out by prefix. Both run in the unit job; its audit digest is updated. Claude-Session: https://claude.ai/code/session_01BUBanXuSck62cxd3dpZ1oA
CHANGESET.md at the root records both halves of what swxtch is: every upstream sync merged in, and every change the fork carries on top, each with its status against upstream. Backfilled from history: the fork base, the 2026-09-22 sync (#38) with its conflict resolutions, and the 20 fork changes since. It stays current mechanically rather than by memory: - sync-upstream.ts now merges with --no-commit and adds the sync's entry (range, commit count, conflicted files) inside the sync merge itself. On conflicts the entry is staged with the in-progress merge, and the conventional message goes to MERGE_MSG so the resolver's commit uses it. - script/changeset-check.ts fails a PR against swxtch with no `- **#<number>**` entry. Dependabot and generated sync-upstream-<timestamp> branches are exempt; a hand branch cannot opt out by prefix. Both run in the unit job; its audit digest is updated. Claude-Session: https://claude.ai/code/session_01BUBanXuSck62cxd3dpZ1oA
Syncs
swxtchwith 17 upstream commits fromanomalyco/opencodedev, through2406400f0a.Merged, not rebased
Both were tried in throwaway worktrees before deciding:
bun.lock,search.ts,npm.tsThe conflict surface is small either way — 5 files overlapped out of 108 on our side and 84 on theirs. Rebasing would buy a linear history at the cost of force-pushing
swxtchand orphaning the commits every merged PR points at, which is a poor trade for a fork that will keep syncing.Conflict resolutions
packages/core/src/filesystem/search.ts— took upstream's.Upstream's anomalyco#50439 fixes the same import cycle our #2 did, independently. Theirs is slightly more conservative: it keeps
import type { FileSystem }for the input types where ours also de-namespaced them toFindInput/GlobInput/GrepInput. Both break the cycle the same way, so taking theirs makes this file byte-identical to upstream and removes a permanent rebase conflict.The other half of our #2 — the layer-node walk guard — is not upstream and is preserved. Its tests still pass against upstream's file.
packages/core/src/npm.ts— kept both import sets.One hunk, purely additive:
semverfrom our #28 (compare requested versions, not just dependency names) andcreateRequire/pathToFileURLfrom upstream's anomalyco#50413 (resolve an npm package entrypoint to a file under Node). Unrelated fixes; both survive.bun.lock— regenerated from the merged manifests.packages/web/package.jsonauto-merged (upstream bumped1.18.31→1.18.32).Verification
test/npm.test.tsauto-merged — both sides edited it — so a clean textual merge is not evidence the combined logic works. Ran it, and the tests either side of the resolutions, explicitly:bun install --frozen-lockfile— clean, satisfies the ci: fail when bun.lock does not match the manifests #33 gatebun run typecheck— 30/30packages/coretest/npm.test.ts— 19/19Going through a PR rather than pushing
swxtchdirectly so CI runs the full unit and e2e suites against the merge before the default branch moves.Note
#37 is open against the pre-sync
swxtch. Once this lands, #37 wants rebasing onto the synced base rather than merging on a stale one.🤖 Generated with Claude Code
https://claude.ai/code/session_017iG7xA9wRvNyFYZSXm8inU