You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PRD: Ship canonical opencode with Amicode — retire the fork-built binary from user machines
Important
Problem
Amicode vendors one fork-built binary (harmoniqs/opencode, pinned v1.18.10-amicode.11) that plays two roles: the opencode CLI users get in the Amicode terminal, and the chat server carrying the entire Amicode product surface (18 server route modules + the customized app UI the deck iframes). It updates only when a new VSIX ships, so users sit marketplace-cadence behind upstream anomalyco/opencode (3 releases / 5 days behind at harmoniqs/opencode#159) and upstream bugfixes reach them late.
Approach
Migrate the Amicode surface onto layers that run on a stock canonical binary — the standard plugin loader (the amicode tool pack), config injection (persona/skills/permissions), an extension-host HTTP service (the 18 amicode routes + widget runtime), and an extracted app bundle composing upstream app components — then cut over in ONE release with zero fork-built bytes shipped, plus a runtime auto-updater that adopts new canonical releases after a smoke gate. Key reason: this solves the binary-currency problem outright and converts the maintenance coupling from weekly monorepo merges into a CI-pinned overlay against canonical's public client API.
Approaches Considered
Bridge then flip (updater tracks fork releases now, flip later) — rejected: ships fork bytes indefinitely; the researcher chose one push.
Flip immediately, migrate later — rejected: the 18 routes and the iframed app UI die on a stock binary; migration must complete first.
Fork forever, tightly synced (weekly automated upstream merges) — rejected: users always one merge-hop behind; a bad merge stalls the whole fleet; sentinel cost is permanent.
Scope
In: migration manifest + five M0 feasibility gates; extension-host amicode service (18 route modules, 7 widget sources, parallel-run harness); app-bundle extraction incl. the 72 i18n keys; internal server cutover + dogfood soak; runtime updater (managed install, adopt gate, fault-injection + adopt-lag drills); the cutover release, fork archival, and retiring the #159 sync sentinel.
Out: no incremental user-visible rollout (single cutover release); no touching users' opencode installs outside VS Code; no upstream feature PRs beyond what cutover requires; no new platforms (matrix stays darwin-arm64 / linux-arm64 / linux-x64, Windows via WSL).
Assumptions / Open Qs
Five unknowns are M0 gates, each answered with evidence before code moves: (1) canonical release assets carry verifiable digests; (2) the per-boot route-auth password flow has a stock-binary equivalent; (3) the widget/deck iframe origin model tolerates an extension-host service origin; (4) plugin registration is assertable on a stock binary; (5) every adopt-gate check has a confirmed signal source on stock canonical. The plan refuses to proceed on an unverified guess.
User Stories
Onboarding — a researcher installs Amicode on a clean machine (even offline): the Amicode terminal's opencode is canonical upstream, amicode-aware (persona, skills, tools active), seeing the same sessions as the app.
Currency — upstream ships a release; within 48h a connected user runs it, without a VSIX release or any action on their part.
Broken release — an upstream release breaks our surface: the adopt gate fails, the user keeps last-known-good silently, sessions intact.
Existing user — upgrades across the cutover: every session written by the fork-built server remains readable; no capability they use today regresses.
Acceptance Criteria
fresh_install_fork_binaries == 0 — clean VM per platform (incl. WSL), offline: terminal opencode resolves to the vendored canonical bootstrap; no file matches any fork release-asset sha256.
vsix_fork_binary_refs == 0 — shipped lock names anomalyco/opencode, no -amicode. tag, no vendored binary sha from the fork (docs/skills textual mentions out of scope).
route_parity_pct == 100 — 18/18 amicode route modules pass fork-derived contract tests against the extension-host service (golden fixtures from the live fork server for modules known-red on the fork).
app_e2e_unexpected_failures == 0 — ported app e2e suite: every failure on the quarantine list frozen at M0; anything else blocks.
drill_adopt_lag_h <= 48 — a gate-passing upstream release goes from publish to adoption marker within 48h on a connected test machine.
failed_update_data_loss == 0 — corrupted-download, plugin-load-failure, and app-health-failure drills each end with sessions intact and last-known-good current.
cutover_session_retention_pct == 100 — dogfood DB + synthetic corpus (≥500 sessions, all part types) structurally identical pre/post cutover.
Key Decisions
One push — no incremental user-visible rollout; the cutover release is the first user-visible change and ships zero fork-built bytes.
Managed canonical wins — inside the Amicode terminal the extension-managed binary resolves first on PATH; user installs elsewhere untouched.
Auto-adopt after smoke gate — activation + daily checks; adoption is an atomic symlink swap only after: digest verification, boot smoke, plugin-registration assert for the amicode tool pack, and app + service health against a consistent (sqlite-backup) copy of the live DB.
Port, don't rewrite — the 18 route modules move wholesale into the extension host; parity is judged by fork-derived contract tests, with golden fixtures recorded from the running fork server for the modules whose tests are known-red on the fork itself.
Vocabulary — upstream = anomalyco/opencode ("canonical opencode"); the fork is never user-facing. Code comments that call the fork binary "canonical" are corrected in the app-bundle milestone.
Modules & Interfaces
Plugin pack (unchanged) — amicode tools via opencode's standard plugin loader; single-export contract.
Extension-host amicode service (new) — the ported routes serving widgets, vault browser, connections, and amicode app calls; the deck shell's iframe origin check widens to it.
App bundle (new, extracted from the fork) — composes upstream app components; CI-pinned against canonical releases; owns the amicode i18n keys.
Runtime updater (new) — managed install under the amico state dir with a current symlink; the VSIX vendors one canonical copy per platform as offline bootstrap.
Testing Decisions
Parity via fork-derived contract tests + golden fixtures; app e2e ported with a frozen quarantine list; three fault-injection drills plus a live adopt-lag drill; retention corpus ≥500 sessions; clean-VM matrix per platform including WSL; parallel-run harness (extension service alongside the fork server) as the migration's verification backbone.
Risks
App↔canonical client-API drift becomes the recurring post-cutover cost; CI-pinned overlay is the mitigation, and breaking releases hold users on last-known-good by design.
The app-bundle extraction is the long pole; the parallel-run harness de-risks taking it slowly.
Post-adoption breakage (passes gate, breaks later) heals on the next release; the existing binary-override setting remains the manual escape hatch.
Last-known-good is never deleted; adoption only via the full adopt gate.
The chat DB stays pinned by the extension across every spawn — the binary never picks its DB by build channel (the 2026-08-08 channel-flip incident).
No coupling to canonical internals; supported surfaces are the plugin API, config injection, and the documented client HTTP API. No feature is added by re-forking.
The fork's default branch is never force-pushed; the repo is archived, not deleted.
All work on Harmoniqs repos goes through issue + PR (development gate).
Prior Art / Patterns
Vault spec + compiled plan (durable record): armonia-aaron-trowbridge/amicode/specs/spec-20260820-044920-ship-canonical-opencode.md and amicode/plans/plan-20260820-044920-ship-canonical-opencode.md
AMICODE-PATCHES.md in the fork — authoritative patch log and sync history
The extension's binary-resolution override (config → vendored) and the vendoring lock/script that already parameterize the source repo
The staging-project config-injection pattern (persona + skills + plugins onto a server binary) — proof the amicode-info layer is already binary-agnostic
Source
Durable record: personal Armonia vault, amicode/specs/spec-20260820-044920-ship-canonical-opencode.md (deliberated 2026-08-20, manual adversarial review — 1 blocking contradiction fixed, 9 advisories) · compiled plan at amicode/plans/plan-20260820-044920-ship-canonical-opencode.md · related: harmoniqs/opencode#159
Notes
Decisions locked with the researcher 2026-08-20: one-push cutover; managed-canonical PATH precedence inside the Amicode terminal; auto-adopt after smoke gate. The spec's deliberation was hand-run (spec tooling unavailable on the host) — a weaker review claim than a tooled one, noted for the record.
PRD: Ship canonical opencode with Amicode — retire the fork-built binary from user machines
Important
Problem
Amicode vendors one fork-built binary (harmoniqs/opencode, pinned
v1.18.10-amicode.11) that plays two roles: theopencodeCLI users get in the Amicode terminal, and the chat server carrying the entire Amicode product surface (18 server route modules + the customized app UI the deck iframes). It updates only when a new VSIX ships, so users sit marketplace-cadence behind upstreamanomalyco/opencode(3 releases / 5 days behind at harmoniqs/opencode#159) and upstream bugfixes reach them late.Approach
Migrate the Amicode surface onto layers that run on a stock canonical binary — the standard plugin loader (the amicode tool pack), config injection (persona/skills/permissions), an extension-host HTTP service (the 18 amicode routes + widget runtime), and an extracted app bundle composing upstream app components — then cut over in ONE release with zero fork-built bytes shipped, plus a runtime auto-updater that adopts new canonical releases after a smoke gate. Key reason: this solves the binary-currency problem outright and converts the maintenance coupling from weekly monorepo merges into a CI-pinned overlay against canonical's public client API.
Approaches Considered
Scope
In: migration manifest + five M0 feasibility gates; extension-host amicode service (18 route modules, 7 widget sources, parallel-run harness); app-bundle extraction incl. the 72 i18n keys; internal server cutover + dogfood soak; runtime updater (managed install, adopt gate, fault-injection + adopt-lag drills); the cutover release, fork archival, and retiring the #159 sync sentinel.
Out: no incremental user-visible rollout (single cutover release); no touching users' opencode installs outside VS Code; no upstream feature PRs beyond what cutover requires; no new platforms (matrix stays darwin-arm64 / linux-arm64 / linux-x64, Windows via WSL).
Assumptions / Open Qs
Five unknowns are M0 gates, each answered with evidence before code moves: (1) canonical release assets carry verifiable digests; (2) the per-boot route-auth password flow has a stock-binary equivalent; (3) the widget/deck iframe origin model tolerates an extension-host service origin; (4) plugin registration is assertable on a stock binary; (5) every adopt-gate check has a confirmed signal source on stock canonical. The plan refuses to proceed on an unverified guess.
User Stories
opencodeis canonical upstream, amicode-aware (persona, skills, tools active), seeing the same sessions as the app.Acceptance Criteria
fresh_install_fork_binaries == 0— clean VM per platform (incl. WSL), offline: terminal opencode resolves to the vendored canonical bootstrap; no file matches any fork release-asset sha256.vsix_fork_binary_refs == 0— shipped lock names anomalyco/opencode, no-amicode.tag, no vendored binary sha from the fork (docs/skills textual mentions out of scope).route_parity_pct == 100— 18/18 amicode route modules pass fork-derived contract tests against the extension-host service (golden fixtures from the live fork server for modules known-red on the fork).app_e2e_unexpected_failures == 0— ported app e2e suite: every failure on the quarantine list frozen at M0; anything else blocks.drill_adopt_lag_h <= 48— a gate-passing upstream release goes from publish to adoption marker within 48h on a connected test machine.failed_update_data_loss == 0— corrupted-download, plugin-load-failure, and app-health-failure drills each end with sessions intact and last-known-good current.cutover_session_retention_pct == 100— dogfood DB + synthetic corpus (≥500 sessions, all part types) structurally identical pre/post cutover.Key Decisions
anomalyco/opencode("canonical opencode"); the fork is never user-facing. Code comments that call the fork binary "canonical" are corrected in the app-bundle milestone.Modules & Interfaces
currentsymlink; the VSIX vendors one canonical copy per platform as offline bootstrap.Testing Decisions
Parity via fork-derived contract tests + golden fixtures; app e2e ported with a frozen quarantine list; three fault-injection drills plus a live adopt-lag drill; retention corpus ≥500 sessions; clean-VM matrix per platform including WSL; parallel-run harness (extension service alongside the fork server) as the migration's verification backbone.
Risks
Constraints & Invariants
Prior Art / Patterns
armonia-aaron-trowbridge/amicode/specs/spec-20260820-044920-ship-canonical-opencode.mdandamicode/plans/plan-20260820-044920-ship-canonical-opencode.mdSource
Durable record: personal Armonia vault,
amicode/specs/spec-20260820-044920-ship-canonical-opencode.md(deliberated 2026-08-20, manual adversarial review — 1 blocking contradiction fixed, 9 advisories) · compiled plan atamicode/plans/plan-20260820-044920-ship-canonical-opencode.md· related: harmoniqs/opencode#159Notes
Decisions locked with the researcher 2026-08-20: one-push cutover; managed-canonical PATH precedence inside the Amicode terminal; auto-adopt after smoke gate. The spec's deliberation was hand-run (spec tooling unavailable on the host) — a weaker review claim than a tooled one, noted for the record.