Skip to content

β.2: vendor + pin opencode (closes #2) - #8

Merged
jack-champagne merged 18 commits into
mainfrom
rchari/beta2-vendor-opencode
Jun 19, 2026
Merged

β.2: vendor + pin opencode (closes #2)#8
jack-champagne merged 18 commits into
mainfrom
rchari/beta2-vendor-opencode

Conversation

@Rchari1

@Rchari1 Rchari1 commented Jun 10, 2026

Copy link
Copy Markdown
Member

Closes #2. Stacked on #7 (β.1 workspace layout) — base will retarget to main automatically when #7 merges.

Implements spec-20260610-155955-vendor-opencode (in amico#132): the extension no longer assumes opencode on $PATH.

What this is

  • opencode.lock.json — committed pin: opencode v1.17.3, per-platform SHA256 (darwin-arm64 + linux-x64). Bumping the pin = one-file PR, gated by CI.
  • scripts/fetch_opencode.mjs — zero-dep download-at-build: SHA256-verified against the manifest (hard fail, no retry/override on mismatch — supply-chain signal), unpack-to-temp + atomic rename, idempotent (.sha256 stamp → offline repeat builds), --record mode for pin bumps. vendor/ is gitignored.
  • src/opencode_binary.ts — resolution: config override (dev-only) → vendored path from the extension install dir → hard error with fetch/reinstall instructions. No $PATH fallback (§4 Assumption 4 stays dead). Config default "opencode""". On a missing binary the extension still activates (inspector/watcher/commands) with chat disabled.
  • test/boot_smoke.mjs — the S35 gate: synthesized project → vendored binary serveGET /event → 200 text/event-stream → clean SIGTERM exit. No LLM creds needed. Runs as a two-platform CI matrix (ubuntu-latest + macos-14) and as the named test:smoke script β.4's packaging step will call.
  • .vscodeignore — exists so vsce does NOT fall back to .gitignore (which would silently exclude the binary from the VSIX); !vendor/** negation makes the intent explicit.
  • Spike smoke tests deleted (smoke_cli, smoke_opencode_boot, opencode_boot_harness, vscode_shim); extension now has a real vitest unit suite (10 tests) in the fast CI job (pnpm -r run test).

AC → evidence

Issue AC Evidence
VSIX ships opencode at a fixed SHA; build fails unless /event SSE 200 opencode.lock.json + fetcher mismatch tests; local smoke: GET /event → 200 (text/event-stream) … PASS on v1.17.3; CI boot-smoke matrix
ServerManager spawns the vendored binary, not $PATH opencode_binary.ts resolution tests; extension.ts wiring; config default ""

Notes

  • v1.17.3 passed the smoke on the first try — no walk-back needed despite the spike being written against 1.3.x. (β.5 owns any SSE payload drift; this PR guarantees boot + /event.)
  • Spec deviations (all noted in the plan): smoke file is boot_smoke.mjs (plain node) so vitest's glob can't pull a network test into the hermetic suite; the fetcher buffers the download in memory rather than a temp file (outcome-equivalent, nothing half-written); idempotent path prints up to date: instead of exiting silently.
  • For β.4: package with vsce package per platform after fetch:opencode --platform <target>; .vscodeignore already ships vendor/**.

🤖 Generated with Claude Code

Rchari1 and others added 11 commits June 10, 2026 11:22
…ension

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ract enforcement

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ash spike (S31 grep green)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ontract end-to-end

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@jack-champagne jack-champagne left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

β.2 looks solid — approving in spirit. Pulled the stacked branch locally and ran it end-to-end: build/typecheck green, fast tier 44 (amico-run) + 10 (extension) passing, fetch:opencode downloaded the real v1.17.3 linux-x64 and the committed SHA verified against the live GitHub release, and test:smoke drove the real binary to GET /event → 200 text/event-stream with a clean SIGTERM exit. CI is green on all three jobs, so the darwin-arm64 pin is machine-gated too. Supply-chain handling (archive-hash-before-unpack, hard-fail with no override, atomic temp→rename install, injectable download for hermetic tests) and graceful degradation (chat disabled but the extension still activates) are exactly right.

Two inline notes — one's a question for you on the leftover AMICO_* env wiring, the other a CI-cost suggestion. Neither blocks.

cwd: opencodeProject.projectDir,
env: {
PATH: `${binDir}:${process.env.PATH ?? ""}`,
AMICO_JULIA_SCRIPT: juliaScript,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rchari1 — this AMICO_* env + PATH=binDir:$PATH injection looks like leftover spike wiring, and it cuts against β.1's all-argv / no-AMICO_* contract (S37 / Q90 — amico-run takes everything via argv, nothing from env). I'm inclined to kill it. Before we rip it out: is there something the opencode server still needs these for (a tool the chat slice invokes that reads them), or can β.3 pass them through amico-run flags instead? Want your read.

Comment thread .github/workflows/ci.yml
- uses: actions/setup-node@v4
with: { node-version: 20, cache: pnpm }
- run: pnpm install --frozen-lockfile
- run: pnpm --filter amicode-v2 fetch:opencode

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both matrix legs re-download ~157MB on every run. Worth an actions/cache step keyed on hashFiles('packages/extension/opencode.lock.json'), restoring packages/extension/vendor/ before this step — the .sha256 idempotency stamp already makes fetch:opencode a no-op on a cache hit, so unchanged pins skip the download entirely.

Rchari1 and others added 6 commits June 17, 2026 12:13
…xpected-throw→exit 64, updateLatest per-runId temp (concurrent-submit race), version single-sourced from package.json; solve_common.jl on Piccolo 1.19 via public Piccolo.Callbacks (no reach-through)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n hashes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ion (S35)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e spike smoke tests

v1.17.3 passes: GET /event → 200 text/event-stream against a synthesized
project, clean SIGTERM exit. No walk-back needed despite the 1.3.x-era spike.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e matrix; .vscodeignore ships vendor/

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Rchari1
Rchari1 force-pushed the rchari/beta2-vendor-opencode branch from 4bb031b to 26d9018 Compare June 17, 2026 16:14
@Rchari1

Rchari1 commented Jun 17, 2026

Copy link
Copy Markdown
Member Author

Thanks — on your two notes:

  • AMICO_* env + PATH=binDir:$PATH (extension.ts:88): you're right it's leftover spike wiring against β.1's all-argv/no-env contract (S37/Q90). Already removed in β.3+β.5: AGENTS.md + vetted template + chat→solve→inspector slice (closes #3) #9 (β.3 Task 4): the spawn env no longer carries AMICO_JULIA_SCRIPT/PROJECT/RUNS_ROOT — amico-run is argv-only, and chat→solve drives it purely via flags. PATH now carries only the amico-run launcher dir (so opencode's bash can resolve amico-run); the Julia project reaches the agent through AGENTS.md (substituted at session-copy), passed as --project. So nothing reads those env vars anymore.
  • CI cache for the 157MB opencode download: good call — I'll add an actions/cache step keyed on hashFiles('packages/extension/opencode.lock.json') restoring packages/extension/vendor/ before fetch:opencode (the .sha256 stamp already makes it a no-op on a cache hit). Tracking it as a fast-follow so it doesn't churn the stack mid-review; flag if you'd rather I fold it in now.

(Branch force-updated from the β.1 rebase — same content, just restacked on the #7 fixes.)

@jack-champagne
jack-champagne deleted the branch main June 18, 2026 06:29
@jack-champagne
jack-champagne changed the base branch from rchari/beta1-amico-run to main June 18, 2026 06:31
#7 was squash-merged (4415f02), flattening beta1's history; beta2 already
contains beta1's changes via its original commits, so this records main as an
ancestor without altering beta2's tree (-s ours). Lets #8 reach main with a
merge commit — no history rewrite, branch stays fast-forwardable.
@jack-champagne
jack-champagne merged commit eb978e2 into main Jun 19, 2026
3 checks passed
jack-champagne added a commit that referenced this pull request Jul 16, 2026
feat: amicode-managed Julia setup via juliaup (#8, layers 1-3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

β.2 — Vendor + pin opencode in the VSIX

2 participants