Repository navigation
Description
Important
Problem — harmoniqs/opencode is 5 days / 77 commits / 3 releases behind anomalyco/opencode (v1.18.12 @ 7fe99387 from 2026-08-04 → v1.18.15 @ d7b115f + HEAD 0bff28de on 2026-08-09, 493 files +71454/-4423). Drift includes RTL/i18n, markdown-worker, and chronological message-ordering changes that touch fork-owned hotspots (message-timeline.tsx, markdown.tsx, language.tsx, titlebar.tsx). Cutting the next v*-amicode.* release without syncing bakes stale upstream bugfixes into the shipped binary and raises the next sync's conflict cost.
Approach — Land the one-off sync (v1.18.12 → v1.18.15+, 27 conflict files hand-merged) and, in the same slice, make future syncs automated: a scheduled notturno-style sentinel that fetches anomalyco/opencode dev, opens notturno/merge-upstream-YYYY-MM-DD, runs a parity-manifest + OPENCODE_CHANNEL=dev gate check, and posts a PR against local/amicode. Keep the fork — don't rebase away amicode surfaces.
Scope — in: one-off merge to 0bff28de (or v1.18.15), resolution of 27 conflict files, AMICODE-PATCHES.md update + tag v1.18.15-amicode.1, sentinel automation (schedule + manual dispatch), docs for sst → anomalyco remote rename. out: dropping the fork, switching default branch, or changing release channel semantics.
Assumptions — local/amicode stays default branch; anomalyco/opencode dev is the canonical upstream; OPENCODE_CHANNEL=dev remains the gate for amicode surfaces; amicode-release.yml tag-triggered release stays.
Acceptance Criteria
-
local/amicodemergesanomalyco/opencodedev@0bff28de(or newerv1.18.15+if HEAD moves) with all 27 conflict files resolved per patch-stack policy (adopt upstream bugfixes, keep fork branding/KaTeX/entity-rail/bug-dock, re-deletedebug-bar.tsx). -
AMICODE-PATCHES.mdlogs the sync (upstream SHA, file counts, decisions) and header points toanomalyco/opencode;package.jsonworkspaces bump to1.18.15. -
env -u OPENCODE_CONFIG_CONTENT -u OPENCODE_SERVER_PASSWORD bun test+bun run typecheckpass (known flakeshttpapi-v2-pty,project-picker-recent-searchquarantined as before). -
OPENCODE_CHANNEL=devbuild succeeds and binary grepsnewLayoutDesigns:…()=>!0(no prod-channel slip). - Tag
v1.18.15-amicode.1pushed →amicode-release.ymlbuildsopencode-linux-x64+opencode-darwin-arm64artifacts with SHA256SUMS. - Scheduled automation exists (weekly +
workflow_dispatch) that: re-addsupstreamasanomalyco/opencodeif missing, fetchesdev, createsnotturno/merge-upstream-YYYY-MM-DD, attempts merge, and opens/updates a PR againstlocal/amicodewith conflict summary + parity manifest. Zero-conflict merges auto-open; conflicted merges post the 27-file checklist. - No silent downgrade: if a better tier/template exists but needs entitlement, automation surfaces
blocked_higherinstead of downgrading.
Testing Decisions
Extend existing suites; create none. Primary signals: bun test (with env leak quarantine), bun run typecheck, script/build.ts --single --skip-install channel-gate grep, and smoke launch of built binary (entity rail / ask cards / vaults still mount). New automation gets a dry-run dispatch test (manual workflow_dispatch on a no-op day).
Key Decisions
- Merge, not rebase — preserve
local/amicodehistory andAMICODE-PATCHES.mdmerge-commit traceability (1f09d0dc5/50f8eb003pattern). - Sentinel lives in
harmoniqs/amicoor as fork GH workflow —notturnohermetic clone previously failed on missinggit identity(harmoniqs/amico#322, fixed#324); reuse that fix rather than inventing a new merger. - Upstream remote is
anomalyco/opencode—sst/opencodeis stale (rename0cf029478); update re-add logic andAMICODE-PATCHES.mdhistorical refs. - i18n parity via
script/translate-app.ts— prefer upstream's generator over manual EN fallback fill; fallback to copy-EN for 40 new locales if generator unavailable. - keep fork, pull mothership improvements — automation is pull-only; fork-owned surfaces (
AmicodeThemeBridge,draft-store,markedKaTeX macros) are never auto-resolved totheirs.
Constraints & Invariants
local/amicoderemainsorigin/HEAD; never force-push it.OPENCODE_CHANNEL=devon every build that ships amicode surfaces (gotcha 2 in patch log).debug-bar.tsxstays deleted on the fork;marked.tsx→marked-theme.tsxextraction must re-thread KaTeX macros.bun.lockresolution istheirs+bun install(mechanical).- Automation never pushes to
upstream; push URL forupstreamstays disabled.
Prior Art
AMICODE-PATCHES.md(sync 2026-08-01: 78 conflicts, 2026-08-04: 0 conflicts, sentinel phantom-conflict note)packages/opencode/script/build.ts+packages/script/src/index.ts(version/channel,OPENCODE_VERSION/OPENCODE_CHANNEL).github/workflows/publish.yml(upstream, guardedanomalyco/opencodeonly) +.github/workflows/amicode-release.yml(fork, tag-triggered, channel-gate grep)harmoniqs/amico#322/harmoniqs/amico#324(notturno sentinel identity fix)- dry worktree:
7fe99387..0bff28de77 commits / 493 files,cf4f06b41..d1ea581d4101 fork commits, 27-file conflict set (110 overlap)
Notes
- Upstream drift as of 2026-08-09:
v1.18.13RTL/plural,v1.18.14retry/proxy,v1.18.15chronological ordering + session-export. Dry merge shows high-risk files:app.tsx,entry.tsx,language.tsx,titlebar.tsx,session-context-tab.tsx,message-timeline.tsx,markdown.tsx,message-part.tsx,marked.tsx,desktop-menu.ts. - No
v1.18.12-amicode.*tag was cut after last sync — this slice should tagv1.18.15-amicode.1directly. - Project board:
harmoniqsorg board (Backlog → Ready → In Progress → In Review → Done); degrade silently ifghlacksread:project.
Activity
feat(ci): automate upstream sync with notturno sentinel (weekly + dis…
jeonghun-jj-lee commentedon Aug 10, 2026
Resolution Plan — Upstream Sync v1.18.16
@Rchari1 — here's the detailed resolution plan for the 27 conflict files. The design was worked out in a deep-dive session analyzing both sides of every conflict.
TL;DR
159-upstream-sync-automation/ PR Automate upstream sync: notturno sentinel (weekly + dispatch) — keep fork, pull mothership #160)Current State
local/amicode)upstream/dev)v1.18.10-amicode.4(2026-08-04)1.18.101.18.16Merge-base:
7fe993879f(v1.18.12 tag)Phase 1 — Foundation (3 files, must land first)
These change APIs/exports that Phase 2 files depend on.
packages/ui/src/context/marked.tsxmarked-katex.tsbesidemarked-parser.ts(containsKATEX_MACROS,singleDollarInlineRegex,katexExtension,renderMathInText; registered as a marked extension in the worker's parser).packages/session-ui/src/components/markdown.tsxparseMarkdown()architecture. Our file-ref linkification + external-link bridging stay as post-render DOM ops indecorate()(run after worker returns HTML).normalizeDisplayMathgoes into the worker pipeline.packages/session-ui/package.json1.18.16+ dep removals (katex/marked-shiki/marked-katex-extension moved to worker package). Keep ourmarkdown-file-refsexport.renderToStringmust work inside a web worker (no DOM access). It does — KaTeX has a server-side mode. But test this early.Phase 2 — Feature Files (11 files, upstream-first)
For each file:
git checkout upstream/dev -- <file>, then re-apply fork additions via manual edit.app.tsxMarkedProviderremoval,UiI18nBridgewithlayoutLocale/plural,onNativeTranslationsAmicodeThemeBridge,AmicodeFileRefBridge,AmicodeSplash,SplitProvider,WorkbenchProvider,lockThemeId="oc-2"entry.tsxloadInitialLocale()async wrapper around renderwebZoom,adoptHiddenProject,adoptBugReportFlag, URL param cleanupmessage-timeline.tsxfindIndexnot string<), session export, RTL (ms-auto,-end-1),language.plural()scrollToEndfixmessage-part.tsxpartDefaultOpenextraction, RTLdir="ltr"/"auto", pending tool details,PacedMarkdownalways-on, i18n'd labelsAmicoSkillChip, receipt-run collapsing,message-part-groups, shell row labels,copyTextToClipboardbridgetitlebar.tsxlanguage.t(...),webSearchProviderLabeli18nnavigateTab, sidebar-left removal, "BETA" channel indicator, update button accent stylinglayout.tsxstart-0/end-0/border-s/rounded-ss/inset-inline-start),logs.exportdesktop-onlySplitFrame,WorkbenchBridge, debug-bar removalsession.tsxfindIndexfix, RTL-end-1,rolledusesslice(index)useAmicodeCommands,postRouteInfo,setSessionCopyProvider, work-column width logicsession-context-tab.tsxButtonimportlanguage.tsxDirection,pluralCategory,DesktopNativeLocale)desktop-menu.tslabelKey+DesktopNativeKey)en.ts. Keep accelerators for macOS zoom.placeholder.tst("ui.promptInput.placeholder.normal", {...})"Ask Amico anything, / for commands, @ for context..."Key upstream bugfixes we're adopting:
findIndexinstead of string<comparison for boundary/rollback!running())PacedMarkdownalways-on (smoother streaming)Phase 3 — Mechanical (13 files)
debug-bar.tsxsettings-model.ts+.test.tsui.ts(server/shared CSP)blob:additionhttpapi-ui.test.tsmarkdown-stream.test.tsnormalizeDisplayMathtests + upstream's projection/streaming testsNon-conflicting fork patches (preserved as-is, no action)
request.ts—PROMPT_COMMUNICATINGinjection (rich chat output for amicode sessions)communicating.txt— shared communication rules promptpackages/app/src/amicode/*— entity rail, connections, bug dock, thinking linepackages/opencode/src/server/amicode/*— Pasqal auth, connections routespackages/app/src/pages/session/composer/bug-dock*— bug report dockprovider/transform.ts— already byte-identical between fork and upstream (patch Widget grid UX: drag to move, Add-widget picker, create-via-chat #24 worked)Automation Workflow
.github/workflows/sync-upstream.yml— lands in this same PR.Steps:
upstreamremote asanomalyco/opencode(push URL disabled)git fetch upstream devnotturno/merge-upstream-YYYY-MM-DDgit merge upstream/dev --no-commitlocal/amicodewith parity manifestVerification Gates
All must pass before merge:
env -u OPENCODE_CONFIG_CONTENT -u OPENCODE_SERVER_PASSWORD bun test(quarantine:httpapi-v2-pty,project-picker-recent-search)bun run typecheckOPENCODE_CHANNEL=devbuild succeeds +grep 'newLayoutDesigns:…()=>!0'confirms channel gate--version→1.18.16, amicode surfaces render (entity rail, KaTeX math in chat)After merge
v1.18.16-amicode.1→ triggersamicode-release.ymlAMICODE-PATCHES.mdheader (upstream SHA, file counts, per-file decisions)opencode.lock.jsonref in the amicode extension repoApproach considered and rejected
fix(app): show the agent picker whenever there is a real choice (#208) (