DashboardcliSession 1W0vc18fUQ99

Session 1W0vc18fUQ99

Full ID: 1W0vc18fUQ99w7CwT
Messages: 227
Distillations: 50
Time range: 2026-09-09 09:29:50 — 2026-09-09 14:52:41

Conversation (227 messages)

Read-only analysis in /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade. Analyze packages/cli/src/lib/delta-upgrade.ts, relevant tests, and binpatch 0.4.2 public source/API (use GitHub/raw source, never node_modules). Determine the smallest exact changes needed to pass an explicit UpgradeSource through stable/nightly delta resolution and prefetch, including support for Toolkit tags cli@<version> and preserving legacy unprefixed tags. Identify whether binpatch githubReleaseSource supports tag prefixes; if not, propose a minimal adapter that does not mix repositories. Identify exact tests to add/update. Do not edit files or run broad tests. Return file/symbol-level recommendations and risks.

gateway · 2026-09-09 09:29:50
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade</path>
<type>directory</type>
<entries>
.craft.yml
.git
.github/
.gitignore
.lore.md
.nojekyll
.npmrc
AGENTS.md
apps/
CHANGELOG.md
codemods/
LICENSE.md
node_modules/
package.json
packages/
pnpm-lock.yaml
pnpm-workspace.yaml
README.md

(18 entries)
</entries>
gateway · 2026-09-09 09:30:18
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/AGENTS.md</path>
<type>file</type>
<content>
1: # Jared (Outpost agent)
2: 
3: Autonomous GitHub coding agent. Work in `/workspace/repo`.
4: 
5: ## Model tiers
6: 
7: The primary model is chosen per event (see `src/agents/models.ts`): heavy for
8: code-producing situations, cheaper for lightweight ones.
9: 
10: | Role | Subagent | Model |
11: | --- | --- | --- |
12: | Triage / plan / review (heavy) | (primary Jared) | Claude Opus 4.8 |
13: | Triage / plan / review (light) | (primary Jared) | xAI Grok 4.3 |
14: | Explore | `explore` | OpenAI gpt-5-mini |
15: | Implement | `implement` | Moonshot kimi-k2.7-code |
16: | Ship (commit/push/PR) | `ship` | xAI Grok (`grok-build-0.1`) |
17: 
18: Pipeline: triage → explore → plan → implement → review → ship.
19: (`worker` is a deprecated alias of `implement`.)
20: 
21: Operators also talk to Jared directly from the Outpost dashboard. ...
gateway · 2026-09-09 09:30:28
result
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/AGENTS.md
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/AGENTS.md
gateway · 2026-09-09 09:30:35
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/AGENTS.md</path>
<type>file</type>
<content>
1: # AGENTS.md
2: 
3: Guidelines for AI agents working in this codebase.
4: 
5: ## Project Overview
6: 
7: **Sentry CLI** is a command-line interface for [Sentry](https://sentry.io), built with Node.js, [pnpm](https://pnpm.io), and [Stricli](https://bloomberg.github.io/stricli/). It lives in `packages/cli` of a pnpm workspace; the docs site lives in `apps/cli-docs`. ...
gateway · 2026-09-09 09:30:50
result
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.mocked.test.ts
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/e2e/delta-upgrade.test.ts
gateway · 2026-09-09 09:30:58
result
Found 94 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/package.json:
  Line 111:     "binpatch": "^0.4.2",


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/e2e/delta-upgrade.test.ts:
  Line 18: import { applyPatch, applyPatchChainInMemory } from "binpatch";


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/init.test.ts:
  Line 22: import * as prefetchNs from "../../src/lib/init/org-prefetch.js";

  Line 23: import { resetPrefetch } from "../../src/lib/init/org-prefetch.js";

  Line 85:   warmSpy = vi.spyOn(prefetchNs, "warmOrgDetection").mockImplementation(

  Line 581:     test("warms prefetch when org is not explicit", async () => {

  Line 588:     test("skips prefetch when org is explicit", async () => {

  Line 594:     test("skips prefetch ...
gateway · 2026-09-09 09:31:08
result
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/types/feedback.ts:
  Line 120:     source: optional(


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/types/dashboard.ts:
  Line 1053:   source: string(),


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/custom-ca.ts:
  Line 136:   const sources: { path: string; source: CaSource; label: string }[] = [

  Line 137:     { path: storedPath, source: "default", label: "stored default" },

  Line 140:       source: "env",


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/telemetry.ts:
  Line 115:   source: string;

  Line 132:     return { enabled: false, source: `env:${TELEMETRY_ENV_VAR}` };

  Line ...
gateway · 2026-09-09 09:31:19
result
No files found
gateway · 2026-09-09 09:31:29
result
No files found
gateway · 2026-09-09 09:31:44
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts</path>
<type>file</type>
<content>
1: /** Delta upgrade discovery and application backed by binpatch. */
2: 
3: import { join } from "node:path";
4: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
5: import * as Sentry from "@sentry/node-core/light";
6: import {
7:   applyPatchChainInMemory,
8:   extractStableChain as binpatchExtractStableChain,
9:   filterAndSortChainTags as binpatchFilterAndSortChainTags,
10:   validateChainStep as binpatchValidateChainStep,
11:   type DeltaTelemetry,
12:   type DeltaUnavailableReason,
13:   type ExtractStableChainOpts,
14:   type GitHubRelease,
15:   getPatchFromVersion,
16:   getPatchTargetSha256,
17:   ghcrSource,
18:   githubReleaseSource,
19:   type InstrumentHook,
20:   MAX_NIGHTLY_CHAIN_DEPTH,
21:   makeCache,
22:   OciClient,
23:   type OciManifest,
24: ...
gateway · 2026-09-09 09:32:00
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
1: /**
2:  * Binary Management
3:  *
4:  * Shared utilities for installing, replacing, and managing the CLI binary.
5:  * Used by both `setup --install` (fresh installs) and `upgrade` (self-updates).
6:  */
7: 
8: import { spawnSync } from "node:child_process";
9: import {
10:   existsSync,
11:   mkdirSync,
12:   readFileSync,
13:   renameSync,
14:   unlinkSync,
15:   writeFileSync,
16: } from "node:fs";
17: import { chmod, copyFile, mkdir, realpath, unlink } from "node:fs/promises";
18: import { delimiter, dirname, isAbsolute, join, resolve, sep } from "node:path";
19: import { compare as semverCompare } from "semver";
20: import { getUserAgent } from "./constants.js";
21: import {
22:   buildTlsErrorDetail,
23:   customFetch,
24:   isTlsCertError,
25: } from "./custom-ca.js";
26: import { stringifyUnknown, ...
gateway · 2026-09-09 09:32:14
result
Found 41 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts:
  Line 237:       await prefetchNightlyPatches(latestVersion, signal);

  Line 239:       await prefetchStablePatches(latestVersion, signal);


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
  Line 991:   return await attemptDeltaUpgrade(


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts:
  Line 270: export function resolveStableChain(

  Line 278: export async function resolveNightlyChain(opts: {

  Line 487: export function resolveStableDelta(

  Line 505: export function resolveNightlyDelta(

  Line 523: export function attemptDeltaUpgrade(

  Line 615: export function prefetchNightlyPatches(

  Line 622: export function ...
gateway · 2026-09-09 09:32:28
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
850:  */
851: async function waitForBinaryVisible(path: string): Promise<number> {
852:   for (let attempt = 1; attempt <= VERIFY_MAX_ATTEMPTS; attempt++) {
853:     const size = probeBinaryFile(path);
854:     if (size !== null) {
855:       if (attempt > 1) {
856:         log.debug(`Binary became visible after ${attempt} attempts`);
857:       }
858:       return size;
859:     }
860:     if (attempt === VERIFY_MAX_ATTEMPTS) {
861:       break;
862:     }
863:     const delay = VERIFY_BASE_DELAY_MS * 2 ** (attempt - 1);
864:     log.debug(
865:       `Downloaded binary not yet visible at ${path}, retrying in ${delay}ms (attempt ${attempt}/${VERIFY_MAX_ATTEMPTS})`
866:     );
867:     await setTimeout(delay);
868:   }
869:   throw new UpgradeError(
870:     "execution_failed",
871:     `Downloaded binary is ...
gateway · 2026-09-09 09:32:43
result
Found 9 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
  Line 579: /** Result from downloadBinaryToTemp — includes both the binary path and lock path */

  Line 728: async function downloadNightlyToPath(

  Line 761: async function downloadStableToPath(

  Line 881:  * from GHCR using the OCI blob download protocol via {@link downloadNightlyToPath}.

  Line 884:  * {@link downloadStableToPath}.

  Line 902: export async function downloadBinaryToTemp(

  Line 1014:     await downloadNightlyToPath(destPath, version, setMessage);

  Line 1016:     await downloadStableToPath(downloadTag ?? version, destPath, setMessage);

  Line 1131:       return downloadBinaryToTemp(version, downloadTag, offline, setMessage);
gateway · 2026-09-09 09:32:54
result
Found 16 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
  Line 975:     const url = getBinaryDownloadUrl("1.0.0");


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/binary.test.ts:
  Line 34:   resolveUpgradeSource,

  Line 43:     const url = getBinaryDownloadUrl("1.0.0");

  Line 57:     const url = getBinaryDownloadUrl("2.0.0");

  Line 83: describe("resolveUpgradeSource", () => {

  Line 87:     const resolved = await resolveUpgradeSource(async (url) => {

  Line 106:     const resolved = await resolveUpgradeSource(async (url) => {

  Line 129:         resolveUpgradeSource(async (url) => {

  Line 145:       resolveUpgradeSource(async (url) => {

  Line 160:       resolveUpgradeSource(async (url) => ...
gateway · 2026-09-09 09:33:18
result
## feat/toolkit-bridge-upgrade...origin/main [behind 2]
 M packages/cli/src/lib/binary.ts
 M packages/cli/test/lib/binary.test.ts
 M packages/cli/test/lib/ghcr.test.ts
 M packages/cli/test/lib/install-script.test.ts
 packages/cli/src/lib/binary.ts               |  88 +++++++++++++++++++--
 packages/cli/test/lib/binary.test.ts         | 109 +++++++++++++++++++++++++++
 packages/cli/test/lib/ghcr.test.ts           |  30 ++++++++
 packages/cli/test/lib/install-script.test.ts |  10 +++
 4 files changed, 232 insertions(+), 5 deletions(-)
diff --git a/packages/cli/src/lib/binary.ts b/packages/cli/src/lib/binary.ts
index 75582612a..a50bc0949 100644
--- a/packages/cli/src/lib/binary.ts
+++ b/packages/cli/src/lib/binary.ts
@@ -102,6 +102,33 @@ export type InstallationMethod =
   | "yarn"
   | "unknown";
 
+/** A repository pair that hosts CLI stable releases and nightly OCI images. */
+export type UpgradeSource = {
+  /** GitHub `owner/repository` containing CLI release assets. ...
gateway · 2026-09-09 09:33:32
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Unit Tests for Delta Upgrade Module
3:  *
4:  * Tests the exported pure-computation functions that drive chain resolution
5:  * for both stable (GitHub Releases) and nightly (GHCR) channels, plus
6:  * async orchestration functions tested via fetch mocking.
7:  */
8: 
9: import { createHash } from "node:crypto";
10: import { existsSync, unlinkSync } from "node:fs";
11: import { access, readFile } from "node:fs/promises";
12: import { tmpdir } from "node:os";
13: import { join } from "node:path";
14: import { afterEach, beforeEach, describe, expect, test } from "vitest";
15: import { getPlatformBinaryName } from "../../src/lib/binary.js";
16: import {
17:   applyPatchChain,
18:   attemptDeltaUpgrade,
19:   canAttemptDelta,
20:   downloadStablePatch,
21:   type ...
gateway · 2026-09-09 09:33:46
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
850: 
851:     const result = await fetchRecentReleases();
852:     expect(result).toEqual([]);
853:   });
854: });
855: 
856: // downloadStablePatch
857: 
858: describe("downloadStablePatch", () => {
859:   test("returns Uint8Array on success", async () => {
860:     const patchData = new Uint8Array([1, 2, 3, 4, 5]);
861: 
862:     mockFetch(async (url) => {
863:       expect(String(url)).toBe("https://example.com/patch.bin");
864:       return new Response(patchData.buffer as ArrayBuffer, {
865:         status: 200,
866:       });
867:     });
868: 
869:     const result = await downloadStablePatch("https://example.com/patch.bin");
870:     expect(result).not.toBeNull();
871:     expect(result).toEqual(patchData);
872:   });
873: 
874:   test("returns null on HTTP 404", async () => {
875:     ...
gateway · 2026-09-09 09:33:54
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
1550:     const patchData = await readFile(join(fixturesDir, "small.trdiff10"));
1551: 
1552:     const chain: PatchChain = {
1553:       patches: [
1554:         {
1555:           data: new Uint8Array(patchData),
1556:           size: patchData.byteLength,
1557:         },
1558:         {
1559:           data: new Uint8Array(patchData),
1560:           size: patchData.byteLength,
1561:         },
1562:       ],
1563:       totalSize: patchData.byteLength * 2,
1564:       expectedSha256: "anything",
1565:     };
1566: 
1567:     try {
1568:       await applyPatchChain(chain, oldPath, destPath).catch(() => {
1569:         // Expected — second patch applied to mismatched bytes fails verification
1570:       });
1571: 
1572:       // The in-memory chain never creates scratch files on disk. ...
gateway · 2026-09-09 09:34:11
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
700:       tags,
701:       "0.0.0-dev.101",
702:       "0.0.0-dev.102"
703:     );
704:     expect(result).toEqual(["patch-0.0.0-dev.102"]);
705:   });
706: });
707: 
708: // validateChainStep
709: 
710: describe("validateChainStep", () => {
711:   const PATCH_LAYER_NAME = `${getPlatformBinaryName()}.patch`;
712: 
713:   function makeLayer(
714:     title: string,
715:     size: number
716:   ): OciManifest["layers"][number] {
717:     return {
718:       digest: `sha256:${title.replace(/\W/g, "")}`,
719:       mediaType: "application/octet-stream",
720:       size,
721:       annotations: { "org.opencontainers.image.title": title },
722:     };
723:   }
724: 
725:   test("returns version-mismatch when from-version differs", () => {
726:     const manifest = makePatchManifest("0.1.0", {}, [
727:   ...
gateway · 2026-09-09 09:34:27
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.mocked.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Integration tests for delta upgrade orchestration with a non-dev CLI_VERSION.
3:  *
4:  * These tests use `vi.mock()` to override `CLI_VERSION` from constants.js
5:  * so that `canAttemptDelta()` passes its dev-build guard (the real `CLI_VERSION`
6:  * is "0.0.0-dev" in test mode, which short-circuits the orchestrator).
7:  *
8:  * Kept as a sibling file to `delta-upgrade.test.ts` because its
9:  * `vi.mock()` would invert the assumptions of the dev-mode null-return
10:  * tests in that file. Under `bun test --isolate` each file gets a fresh
11:  * module graph, so the mocks here don't leak. ...
gateway · 2026-09-09 09:34:38
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/e2e/delta-upgrade.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * E2E Test: Delta Upgrade via Binary Patching
3:  *
4:  * Downloads two consecutive stable release binaries from GitHub,
5:  * generates a TRDIFF10 patch using zig-bsdiff, and verifies that
6:  * our `applyPatch()` produces byte-identical output.
7:  *
8:  * Requires: zig-bsdiff binary available at /tmp/bsdiff (or via ZIG_BSDIFF_PATH env).
9:  * Skipped in CI unless ZIG_BSDIFF_PATH is set. ...
gateway · 2026-09-09 09:35:06
result
StatusCode: non 2xx status code (401 GET https://api.github.com/search/code?q=%22githubReleaseSource%22+%22binpatch%22)
gateway · 2026-09-09 09:35:17
result
{"bugs":{"url":"https://github.com/BYK/binpatch/issues"},"dist":{"shasum":"48c635e950ded2c620fc932fe1a44e2fdad2d68d","tarball":"https://registry.npmjs.org/binpatch/-/binpatch-0.4.2.tgz","fileCount":6,"integrity":"sha512-aShVdFVzDrqVRlyhDQabzKV6b9suWegARr0IPTer58eNQoo1KqpuCr+VtbwwuirmfXqmWuuxsoZlXJN1tTZBcw==","signatures":[{"sig":"MEUCIQD7P6no2s3UpvTTLw+cyPpgh91Zocgt00IrBp0xnZSKpgIgBKh83uJhzQSZzVKLcSOC5ub2vuveBDMYMq9NQ0yU5S8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/binpatch@0.4.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":206575},"main":"./dist/index.js","name":"binpatch","type":"module","_from":"file:/tmp/craft-cY6qx5/binpatch-0.4.2.tgz","types":"./dist/index.d.ts","author":{"name":"BYK"},"engines":{"node":">=22.15.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"license":"MIT","scripts":{"test":"vitest ...
gateway · 2026-09-09 09:35:39
result
StatusCode: non 2xx status code (404 GET https://api.github.com/repos/BYK/binpatch/git/trees/v0.4.2?recursive=1)
gateway · 2026-09-09 09:35:46
result
[
  {
    "name": "0.4.2",
    "zipball_url": "https://api.github.com/repos/BYK/binpatch/zipball/refs/tags/0.4.2",
    "tarball_url": "https://api.github.com/repos/BYK/binpatch/tarball/refs/tags/0.4.2",
    "commit": {
      "sha": "9ba6bbb8227fcbd2521852d2311c82afac5e9573",
      "url": "https://api.github.com/repos/BYK/binpatch/commits/9ba6bbb8227fcbd2521852d2311c82afac5e9573"
    },
    "node_id": "REF_kwDOThqhQK9yZWZzL3RhZ3MvMC40LjI"
  },
  {
    "name": "0.4.1",
    "zipball_url": "https://api.github.com/repos/BYK/binpatch/zipball/refs/tags/0.4.1",
    "tarball_url": "https://api.github.com/repos/BYK/binpatch/tarball/refs/tags/0.4.1",
    "commit": {
      "sha": "d0593cdd89eb720edddf9644e0753613e4a8e622",
      "url": "https://api.github.com/repos/BYK/binpatch/commits/d0593cdd89eb720edddf9644e0753613e4a8e622"
    },
    "node_id": "REF_kwDOThqhQK9yZWZzL3RhZ3MvMC40LjE"
  },
  {
    "name": "0.4.0",
    "zipball_url": ...
gateway · 2026-09-09 09:35:57
result
{
  "sha": "9ba6bbb8227fcbd2521852d2311c82afac5e9573",
  "url": "https://api.github.com/repos/BYK/binpatch/git/trees/9ba6bbb8227fcbd2521852d2311c82afac5e9573",
  "tree": [
    {
      "path": ".craft.yml",
      "mode": "100644",
      "type": "blob",
      "sha": "36f34fdd754de842419fe5a5cb2844a8c98f80df",
      "size": 1143,
      "url": "https://api.github.com/repos/BYK/binpatch/git/blobs/36f34fdd754de842419fe5a5cb2844a8c98f80df"
    },
    {
      "path": ".github",
      "mode": "040000",
      "type": "tree",
      "sha": "dc6a71d7d4d393c0e072cb45ac745fc2a61f60ef",
      "url": "https://api.github.com/repos/BYK/binpatch/git/trees/dc6a71d7d4d393c0e072cb45ac745fc2a61f60ef"
    },
    {
      "path": ".github/workflows",
      "mode": "040000",
      "type": "tree",
      "sha": "da820a4798f068f6531c69b3544f97601baa4cfa",
      "url": "https://api.github.com/repos/BYK/binpatch/git/trees/da820a4798f068f6531c69b3544f97601baa4cfa"
    },
    {
      "path": ...
gateway · 2026-09-09 09:36:08
result
/**
 * GitHub Release-asset patch source (the "stable" channel).
 *
 * Resolves a patch chain from GitHub Release assets. Each release for the
 * target platform publishes three assets:
 * - `<binaryName>`        — the binary (its digest → expected SHA-256)
 * - `<binaryName>.gz`     — gzipped binary (its size → the ratio gate)
 * - `<binaryName>.patch`  — the delta patch from the previous release
 *
 * The chain is the releases between current and target, oldest-first, capped
 * at {@link MAX_STABLE_CHAIN_DEPTH} and by {@link SIZE_THRESHOLD_RATIO}.
 *
 * All product specifics (owner/repo, binary name, user-agent, fetch) are
 * injected. Generalized from Lore's stable-channel resolver.
 */

import {
  type InstrumentHook,
  MAX_STABLE_CHAIN_DEPTH,
  type PatchChain,
  type PatchLink,
  SIZE_THRESHOLD_RATIO,
} from "../contract";
import type { SourceStrategy } from "../discover";

const SHA256_DIGEST_PATTERN = /^sha256:([0-9a-f]+)$/i;

export type GitHubAsset = {
  name: string;
  ...
gateway · 2026-09-09 09:36:19
result
/**
 * GHCR / OCI patch source (the "nightly" channel).
 *
 * Resolves a patch chain from OCI patch-manifest tags. Patches are published
 * under `<patchTagPrefix><version>` tags whose manifests carry:
 * - annotation `from-version=<prev>` — the chain back-pointer
 * - annotation `sha256-<binaryName>=<hex>` — the target's uncompressed SHA-256
 * - a patch layer whose title is `<binaryName>.patch`
 *
 * The target binary's gzipped size (for the ratio gate) is read from the
 * target's own image manifest (its `<binaryName>.gz` layer). All product
 * specifics — registry, repo, user-agent, binary name, the version→target-tag
 * scheme, and version comparison — are injected. Generalized from Lore's
 * nightly-channel resolver.
 */

import {
  type InstrumentHook,
  MAX_NIGHTLY_CHAIN_DEPTH,
  PATCH_TAG_PREFIX,
  type PatchChain,
  type PatchLink,
  SIZE_THRESHOLD_RATIO,
} from "../contract";
import type { SourceStrategy, UnavailableReporter } from "../discover";
import { BinpatchError } ...
gateway · 2026-09-09 09:36:41
result
/**
 * Chain discovery + resolve-and-apply orchestration.
 *
 * A {@link SourceStrategy} knows how to resolve a {@link PatchChain} from some
 * backing store (an OCI registry, GitHub Release assets, ...). This module ties
 * a strategy together with the offline cache, the apply core, integrity
 * verification, and progress events — with every product-specific concern
 * (version, telemetry, logging, cache location) injected.
 */

import { applyPatchChainInMemory, parsePatchHeader } from "./bspatch";
import type { PatchCache } from "./patch-cache";
import type { DeltaResult, PatchChain } from "./contract";
import { type ProgressHandler, safeProgress } from "./events";

/**
 * A source of patch chains. Given the current and target versions, resolve the
 * ordered chain of patches (oldest hop first) plus the expected final SHA-256,
 * or `null` when no usable chain exists (caller falls back to a full download). ...
gateway · 2026-09-09 09:36:51
result
/**
 * binpatch — reusable binary delta-update engine.
 *
 * Two things, joined by one wire contract (see README):
 * - **apply core** — parse + apply a TRDIFF10/bsdiff patch chain to a binary.
 * - **discovery** — resolve a patch chain from a pluggable `SourceStrategy`
 *   (OCI/GHCR tags or GitHub Release assets), then apply + verify it.
 *
 * Pure Node (`node:*` builtins only), zero product coupling — the consumer
 * injects the cache directory, the download source, version comparison,
 * progress handling, and telemetry.
 */

export {
  addDiffChunk,
  applyPatch,
  applyPatchChainInMemory,
  applyPatchToMemory,
  MAX_OUTPUT_SIZE,
  offtin,
  parsePatchHeader,
  type PatchHeader,
} from "./bspatch";

export {
  type ChainMeta,
  chainFileName,
  makeCache,
  type PatchCache,
  patchFileName,
  type PatchStepMeta,
} from "./patch-cache";

// Wire-contract constants + shared chain types. ...
gateway · 2026-09-09 09:37:47
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts</path>
<type>file</type>
<content>
1: /**
2:  * Background version check for "new version available" notifications.
3:  *
4:  * For nightly builds (CLI_VERSION contains "-dev.<timestamp>"), checks GHCR for the
5:  * latest nightly version via the OCI manifest annotation. For stable builds,
6:  * checks GitHub Releases. Results are cached in the database and shown on
7:  * subsequent runs.
8:  */
9: 
10: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
11: import * as Sentry from "@sentry/node-core/light";
12: import { compare as semverCompare } from "semver";
13: import { CLI_VERSION } from "./constants.js";
14: import { getReleaseChannel } from "./db/release-channel.js";
15: import {
16:   getVersionCheckInfo,
17:   markUpdateNotified,
18:   setVersionCheckInfo,
19: } from ...
gateway · 2026-09-09 09:37:58
result
Found 5 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
  Line 399: export async function fetchLatestFromGitHub(

  Line 433: export async function fetchLatestFromNpm(): Promise<string> {

  Line 467: export async function fetchLatestNightlyVersion(

  Line 503:     return fetchLatestNightlyVersion();

  Line 506:     ? fetchLatestFromGitHub()
gateway · 2026-09-09 09:38:08
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
1: /**
2:  * Upgrade Module
3:  *
4:  * Detects how the CLI was installed and provides self-upgrade functionality.
5:  * Binary management helpers (download URLs, locking, replacement) live in
6:  * binary.ts and are shared with the setup --install flow.
7:  */
8: 
9: import { spawn } from "node:child_process";
10: import {
11:   chmodSync,
12:   closeSync,
13:   existsSync,
14:   openSync,
15:   realpathSync,
16:   statSync,
17:   unlinkSync,
18:   writeSync,
19: } from "node:fs";
20: import { writeFile } from "node:fs/promises";
21: import { homedir } from "node:os";
22: import { dirname, isAbsolute, join, sep } from "node:path";
23: import { setTimeout } from "node:timers/promises";
24: import {
25:   acquireLock,
26:   cleanupOldBinary,
27:   determineInstallDir,
28:   fetchWithUpgradeError,
29:   ...
gateway · 2026-09-09 09:41:53
result
Found 3 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/pnpm-lock.yaml:
  Line 136:       binpatch:

  Line 2169:   binpatch@0.4.2:

  Line 6698:   binpatch@0.4.2: {}
gateway · 2026-09-09 09:42:01
result
Found 13 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts:
  Line 286:             ? await fetchLatestNightlyVersion(signal)

  Line 287:             : await fetchLatestFromGitHub(signal);


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
  Line 399: export async function fetchLatestFromGitHub(

  Line 467: export async function fetchLatestNightlyVersion(

  Line 498: export function fetchLatestVersion(

  Line 503:     return fetchLatestNightlyVersion();

  Line 506:     ? fetchLatestFromGitHub()

  Line 551: export async function versionExists(

  Line 902: export async function downloadBinaryToTemp(

  Line 1131:       return downloadBinaryToTemp(version, downloadTag, offline, ...
gateway · 2026-09-09 09:42:08
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
250:   // Offline mode is only supported for curl-installed binaries — package
251:   // managers always need network to fetch and install packages.
252:   if (offline && method !== "curl") {
253:     throw new UpgradeError(
254:       "unsupported_operation",
255:       "Offline upgrade is only supported for curl-installed binaries."
256:     );
257:   }
258: }
259: 
260: type ResolveTargetOptions = {
261:   method: InstallationMethod;
262:   channel: ReleaseChannel;
263:   versionArg: string | undefined;
264:   channelChanged: boolean;
265:   flags: UpgradeFlags;
266: };
267: 
268: /**
269:  * Result of resolving the target version. ...
gateway · 2026-09-09 09:42:17
result
Found 3 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:
  Line 463:       // CLI-1D3). `downloadBinaryToTemp`'s visibility-race retry loop

  Line 642:       executeUpgrade(method, target, downloadTag, offline, setMessage)

  Line 727:       executeUpgrade("curl", target, downloadTag, undefined, setMessage)
gateway · 2026-09-09 09:42:31
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
560: }
561: 
562: function resolveUpdatedCliPath(
563:   execPath: string,
564:   entryPath: string | undefined,
565:   pathEnv: string | undefined
566: ): string {
567:   return whichSync("sentry", { PATH: pathEnv }) ?? entryPath ?? execPath;
568: }
569: 
570: /**
571:  * Decide which directory a curl upgrade should install into.
572:  *
573:  * Normally the binary stays where it currently lives — pinning the install
574:  * dir keeps an in-place update from relocating a binary that is already on
575:  * the user's `PATH` (upgrade runs setup with `--no-modify-path`, so it can't
576:  * add a new directory to `PATH`).
577:  *
578:  * The one exception is a legacy `~/.sentry/bin` install: those should move to
579:  * the XDG-aligned location so users actually migrate off `~/.sentry`. ...
gateway · 2026-09-09 09:43:54
result
/**
 * Patch Cache
 *
 * File-based cache for delta upgrade patches. Patches are downloaded
 * during background version checks so that an upgrade can apply them
 * offline without any network calls.
 *
 * Cache layout, under the caller-provided cache directory:
 * - <fromVersion>-<toVersion>.patch — raw binary patch data
 * - chain-<fromVersion>-<toVersion>.json — chain metadata
 *
 * Uses file-based storage to avoid bloating a DB with 50-80KB binary
 * blobs. Channel-agnostic — the same version-based naming works for
 * both nightly (GHCR) and stable (GitHub Releases) channels.
 *
 * The cache directory is injected by the consumer via `makeCache(cacheDir)`
 * so this module carries no product-specific coupling (no config-dir
 * lookup, no env vars). Adapted from Sentry CLI's patch-cache.ts. ...
gateway · 2026-09-09 09:44:01
result
Found 1 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/version-check.test.ts:
  Line 474:     expect(infoBefore.latestVersion).toBe("1.0.0");
gateway · 2026-09-09 09:44:08
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/version-check.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Version Check Logic Tests
3:  */
4: 
5: import { setTimeout as sleep } from "node:timers/promises";
6: import { afterEach, beforeEach, describe, expect, test } from "vitest";
7: import { setReleaseChannel } from "../../src/lib/db/release-channel.js";
8: import {
9:   getVersionCheckInfo,
10:   setVersionCheckInfo,
11: } from "../../src/lib/db/version-check.js";
12: import {
13:   ApiError,
14:   ContextError,
15:   ValidationError,
16: } from "../../src/lib/errors.js";
17: import {
18:   abortPendingVersionCheck,
19:   getErrorUpdateNotification,
20:   getUpdateNotification,
21:   maybeCheckForUpdateInBackground,
22:   resetUpdateNotificationState,
23:   shouldSuppressNotification,
24: } from "../../src/lib/version-check.js";
25: import { mockFetch, useTestConfigDir } from ...
gateway · 2026-09-09 09:44:30
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/binary.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Binary Management Tests
3:  *
4:  * Tests for shared binary helpers: install directory selection, paths,
5:  * download URLs, locking, and binary installation.
6:  */
7: 
8: import {
9:   chmodSync,
10:   mkdirSync,
11:   readFileSync,
12:   realpathSync,
13:   rmSync,
14:   symlinkSync,
15:   writeFileSync,
16: } from "node:fs";
17: import { access, readFile, writeFile } from "node:fs/promises";
18: import { join, sep } from "node:path";
19: import { afterEach, beforeEach, describe, expect, test } from "vitest";
20: import {
21:   acquireLock,
22:   compareVersions,
23:   determineInstallDir,
24:   fetchWithUpgradeError,
25:   getBinaryDownloadUrl,
26:   getBinaryFilename,
27:   getBinaryPaths,
28:   getGitHubReleaseByTagUrl,
29:   getLegacyInstallDirs,
30:   getPlatformBinaryName,
31:   ...
gateway · 2026-09-09 09:44:45
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
220:     os = "linux";
221:   }
222:   const arch = process.arch === "arm64" ? "arm64" : "x64";
223:   const libcSuffix = isMusl() ? "-musl" : "";
224:   const suffix = process.platform === "win32" ? ".exe" : "";
225:   return `sentry-${os}-${arch}${libcSuffix}${suffix}`;
226: }
227: 
228: /**
229:  * Build the download URL for a platform-specific binary from GitHub releases.
230:  *
231:  * @param version - Version to download (without 'v' prefix)
232:  * @returns Download URL for the binary
233:  */
234: export function getBinaryDownloadUrl(
235:   version: string,
236:   source: UpgradeSource = PRIMARY_UPGRADE_SOURCE
237: ): string {
238:   const tag = `${source.tagPrefix}${version}`;
239:   return `https://github.com/${source.githubRepo}/releases/download/${tag}/${getPlatformBinaryName()}`;
240: }
241: ...
gateway · 2026-09-09 09:45:24
result
/**
 * Wire-contract constants and shared types.
 *
 * These values are part of the binpatch wire contract — the generator (the
 * publishing side) and this library MUST agree on them. See the package README
 * for the full contract spec.
 */

/** Maximum stable patches to chain before falling back to a full download. */
export const MAX_STABLE_CHAIN_DEPTH = 10;

/** Maximum nightly patches to chain before falling back to a full download. */
export const MAX_NIGHTLY_CHAIN_DEPTH = 30;

/**
 * Maximum ratio of total patch-chain size to the full (gzipped) download size.
 * Above this, a full download is cheaper — abandon the chain.
 */
export const SIZE_THRESHOLD_RATIO = 0.6;

/** GHCR tag prefix under which per-version patch manifests are published. */
export const PATCH_TAG_PREFIX = "patch-";

/** A single link in a patch chain: the raw patch bytes and their size. */
export type PatchLink = {
  data: Uint8Array;
  size: number;
};

/** One from->to hop, used for cache keying. ...
gateway · 2026-09-09 09:47:20
result
diff --git a/packages/cli/src/lib/binary.ts b/packages/cli/src/lib/binary.ts
index 75582612a..bebf1da0c 100644
--- a/packages/cli/src/lib/binary.ts
+++ b/packages/cli/src/lib/binary.ts
@@ -102,6 +102,33 @@ export type InstallationMethod =
   | "yarn"
   | "unknown";
 
+/** A repository pair that hosts CLI stable releases and nightly OCI images. */
+export type UpgradeSource = {
+  /** GitHub `owner/repository` containing CLI release assets. */
+  readonly githubRepo: string;
+  /** GHCR `owner/package` containing CLI nightly images and delta patches. */
+  readonly ghcrRepo: string;
+  /** Prefix attached to CLI release tags in this repository. */
+  readonly tagPrefix: string;
+};
+
+/** Ordered CLI release sources. The resolver falls through only on HTTP 404. ...
gateway · 2026-09-09 09:49:23
result
{
  "url": "https://api.github.com/repos/getsentry/cli/issues/1244",
  "repository_url": "https://api.github.com/repos/getsentry/cli",
  "labels_url": "https://api.github.com/repos/getsentry/cli/issues/1244/labels{/name}",
  "comments_url": "https://api.github.com/repos/getsentry/cli/issues/1244/comments",
  "events_url": "https://api.github.com/repos/getsentry/cli/issues/1244/events",
  "html_url": "https://github.com/getsentry/cli/issues/1244",
  "id": 4890976993,
  "node_id": "I_kwDOQm6jAs8AAAABI4Zi4Q",
  "number": 1244,
  "title": "toolkit merge: bridge CLI release + dual-source upgrade compatibility",
  "user": {
    "login": "BYK",
    "id": 126780,
    "node_id": "MDQ6VXNlcjEyNjc4MA==",
    "avatar_url": "https://avatars.githubusercontent.com/u/126780?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/BYK",
    "html_url": "https://github.com/BYK",
    "followers_url": "https://api.github.com/users/BYK/followers",
    "following_url": ...
gateway · 2026-09-09 09:49:30
result
[
  {
    "url": "https://api.github.com/repos/getsentry/cli/issues/comments/4978828102",
    "html_url": "https://github.com/getsentry/cli/issues/1244#issuecomment-4978828102",
    "issue_url": "https://api.github.com/repos/getsentry/cli/issues/1244",
    "id": 4978828102,
    "node_id": "IC_kwDOQm6jAs8AAAABKMLjRg",
    "user": {
      "login": "BYK",
      "id": 126780,
      "node_id": "MDQ6VXNlcjEyNjc4MA==",
      "avatar_url": "https://avatars.githubusercontent.com/u/126780?v=4",
      "gravatar_id": "",
      "url": "https://api.github.com/users/BYK",
      "html_url": "https://github.com/BYK",
      "followers_url": "https://api.github.com/users/BYK/followers",
      "following_url": "https://api.github.com/users/BYK/following{/other_user}",
      "gists_url": "https://api.github.com/users/BYK/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/BYK/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/BYK/subscriptions",
      ...
gateway · 2026-09-09 09:50:46
result
import { afterEach, describe, expect, it, vi } from "vitest";
import {
  type InstrumentHook,
  extractSha256,
  extractStableChain,
  filterAndSortChainTags,
  getPatchFromVersion,
  getPatchTargetSha256,
  ghcrSource,
  type GitHubRelease,
  githubReleaseSource,
  getStableTargetSha256,
  OciClient,
  type OciManifest,
  validateChainStep,
} from "../src";

// Build a JSON Response for mocked fetch calls.
function json(body: unknown): Response {
  return new Response(JSON.stringify(body), {
    status: 200,
    headers: { "content-type": "application/json" },
  });
}

// A semver-ish comparator matching the gateway's compareVersions contract
// (returns -1 | 0 | 1) for the nightly tag-ordering tests.
function cmp(a: string, b: string): -1 | 0 | 1 {
  const pa = a.split(".").map(Number);
  const pb = b.split(".").map(Number);
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
    const x = pa[i] ?? 0;
    const y = pb[i] ?? ...
gateway · 2026-09-09 09:51:04
result
Found 27 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/ghcr.ts:
  Line 25:   type UpgradeSource,

  Line 197:   sourceOrSignal: UpgradeSource | AbortSignal = PRIMARY_UPGRADE_SOURCE,

  Line 242:   source: UpgradeSource = PRIMARY_UPGRADE_SOURCE

  Line 280:   source: UpgradeSource = PRIMARY_UPGRADE_SOURCE

  Line 350:   source: UpgradeSource = PRIMARY_UPGRADE_SOURCE

  Line 446:   source: UpgradeSource = PRIMARY_UPGRADE_SOURCE

  Line 491:   source: UpgradeSource = PRIMARY_UPGRADE_SOURCE

  Line 534:   source: UpgradeSource = PRIMARY_UPGRADE_SOURCE


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts:
  Line 106: export type UpgradeSource = {

  Line 116: export const UPGRADE_SOURCES: readonly UpgradeSource[] = [

  Line 130: export const PRIMARY_UPGRADE_SOURCE = UPGRADE_SOURCES[0];

  Line 236:   source: ...
gateway · 2026-09-09 09:51:11
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/ghcr.ts</path>
<type>file</type>
<content>
1: /**
2:  * GHCR (GitHub Container Registry) Client
3:  *
4:  * Encapsulates the OCI download protocol for fetching nightly CLI binaries
5:  * from ghcr.io/getsentry/cli. Nightly builds are pushed as OCI artifacts
6:  * via ORAS with the version baked into the manifest annotation.
7:  *
8:  * Key design decisions:
9:  * - Anonymous access: nightly package is public; no token needed beyond the
10:  *   standard ghcr.io anonymous token exchange.
11:  * - Version discovery from manifest annotation: `annotations.version` in the
12:  *   OCI manifest holds the nightly version. Checking the latest version only
13:  *   requires a token exchange + manifest fetch (2 HTTP requests total).
14:  * - Redirect quirk: ghcr.io blob downloads return 307 to Azure Blob Storage. ...
gateway · 2026-09-09 09:51:33
result
diff --git a/packages/cli/src/lib/ghcr.ts b/packages/cli/src/lib/ghcr.ts
index 43d6deb7e..f648ab78a 100644
--- a/packages/cli/src/lib/ghcr.ts
+++ b/packages/cli/src/lib/ghcr.ts
@@ -20,6 +20,10 @@
 import { getUserAgent } from "./constants.js";
 import { customFetch } from "./custom-ca.js";
 import { UpgradeError } from "./errors.js";
+import {
+  PRIMARY_UPGRADE_SOURCE,
+  type UpgradeSource,
+} from "./binary.js";
 
 /** Default timeout for GHCR HTTP requests (10 seconds) */
 const GHCR_REQUEST_TIMEOUT = 10_000;
@@ -130,8 +134,8 @@ async function fetchWithRetry(
   );
 }
 
-/** GHCR repository for CLI distribution */
-export const GHCR_REPO = "getsentry/cli";
+/** Default GHCR repository for CLI distribution. */
+export const GHCR_REPO = PRIMARY_UPGRADE_SOURCE.ghcrRepo;
 
 /** OCI tag for nightly builds */
 export const GHCR_TAG = "nightly";
@@ -189,13 +193,20 @@ export type OciManifest = {
  * @returns Bearer token string
  * @throws {UpgradeError} On network failure or malformed ...
gateway · 2026-09-09 09:54:28
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
700: 
701: /**
702:  * Build the gzip filename for the current platform binary.
703:  *
704:  * Nightly builds are stored in GHCR as `sentry-<os>-<arch>.gz` (or
705:  * `sentry-windows-x64.exe.gz` on Windows). This filename is the
706:  * `org.opencontainers.image.title` annotation on the matching OCI layer.
707:  *
708:  * @returns Filename of the gzip-compressed binary for this platform
709:  */
710: function getNightlyGzFilename(): string {
711:   return `${getPlatformBinaryName()}.gz`;
712: }
713: 
714: /**
715:  * Download a nightly binary from GHCR and decompress it to `destPath`.
716:  *
717:  * Fetches an anonymous token, retrieves the OCI manifest, finds the layer
718:  * matching this platform's `.gz` filename, then downloads and decompresses
719:  * the blob in-stream. ...
gateway · 2026-09-09 09:54:39
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
890:  *
891:  * If the child resolves to the same install path, it takes over the lock via
892:  * process.ppid recognition in acquireLock — the parent's subsequent release
893:  * is then a harmless no-op.
894:  *
895:  * @param version - Target version to download (used for display and comparison)
896:  * @param downloadTag - Git tag to use in the download URL. Defaults to `version`.
897:  *   Pass `NIGHTLY_TAG` ("nightly") when installing from the rolling nightly release
898:  *   so the URL points to the prerelease assets regardless of the version string.
899:  * @returns The downloaded binary path and lock path to release
900:  * @throws {UpgradeError} When download fails
901:  */
902: export async function downloadBinaryToTemp(
903:   version: string,
904:   downloadTag?: string,
905:   offline?: ...
gateway · 2026-09-09 09:54:50
result
Found 7 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts:
  Line 1814:     const result = await attemptDeltaUpgrade(

  Line 1834:     await prefetchNightlyPatches("0.14.0-dev.123");

  Line 1844:     await prefetchStablePatches("0.14.0");


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.mocked.test.ts:
  Line 318:     const result = await attemptDeltaUpgrade(

  Line 335:       const result = await attemptDeltaUpgrade(

  Line 406:       const result = await attemptDeltaUpgrade(

  Line 481:       const result = await attemptDeltaUpgrade(
gateway · 2026-09-09 09:55:00
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.mocked.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Integration tests for delta upgrade orchestration with a non-dev CLI_VERSION.
3:  *
4:  * These tests use `vi.mock()` to override `CLI_VERSION` from constants.js
5:  * so that `canAttemptDelta()` passes its dev-build guard (the real `CLI_VERSION`
6:  * is "0.0.0-dev" in test mode, which short-circuits the orchestrator).
7:  *
8:  * Kept as a sibling file to `delta-upgrade.test.ts` because its
9:  * `vi.mock()` would invert the assumptions of the dev-mode null-return
10:  * tests in that file. Under `bun test --isolate` each file gets a fresh
11:  * module graph, so the mocks here don't leak. ...
gateway · 2026-09-09 09:55:13
result
Found 35 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts:
  Line 18:   githubReleaseSource,

  Line 85:     load(currentVersion, targetVersion) {

  Line 86:       const key = patchCacheKey(currentVersion, targetVersion);

  Line 89:         const result = await base.load(currentVersion, targetVersion);

  Line 123:   return githubReleaseSource({

  Line 124:     releasesUrl: GITHUB_RELEASES_URL,

  Line 145: export function canAttemptDelta(targetVersion: string): boolean {

  Line 149:   if (isNightlyVersion(CLI_VERSION) !== isNightlyVersion(targetVersion)) {

  Line 152:   return !isDowngrade(CLI_VERSION, targetVersion);

  Line 207:   targetVersion: string

  Line 212:     targetVersion,

  Line 272:   targetVersion: string,

  Line 275:   return stableSource().resolveChain(currentVersion, targetVersion, signal);

  Line 281:   targetVersion: string;

  Line 298:     ...
gateway · 2026-09-09 09:55:23
result
StatusCode: non 2xx status code (404 GET https://api.github.com/repos/BYK/binpatch/git/ref/tags/v0.4.2)
gateway · 2026-09-09 09:55:32
result
[
  {
    "name": "0.4.2",
    "zipball_url": "https://api.github.com/repos/BYK/binpatch/zipball/refs/tags/0.4.2",
    "tarball_url": "https://api.github.com/repos/BYK/binpatch/tarball/refs/tags/0.4.2",
    "commit": {
      "sha": "9ba6bbb8227fcbd2521852d2311c82afac5e9573",
      "url": "https://api.github.com/repos/BYK/binpatch/commits/9ba6bbb8227fcbd2521852d2311c82afac5e9573"
    },
    "node_id": "REF_kwDOThqhQK9yZWZzL3RhZ3MvMC40LjI"
  },
  {
    "name": "0.4.1",
    "zipball_url": "https://api.github.com/repos/BYK/binpatch/zipball/refs/tags/0.4.1",
    "tarball_url": "https://api.github.com/repos/BYK/binpatch/tarball/refs/tags/0.4.1",
    "commit": {
      "sha": "d0593cdd89eb720edddf9644e0753613e4a8e622",
      "url": "https://api.github.com/repos/BYK/binpatch/commits/d0593cdd89eb720edddf9644e0753613e4a8e622"
    },
    "node_id": "REF_kwDOThqhQK9yZWZzL3RhZ3MvMC40LjE"
  },
  {
    "name": "0.4.0",
    "zipball_url": ...
gateway · 2026-09-09 09:55:38
result
{
  "name": "binpatch",
  "version": "0.4.2",
  "type": "module",
  "license": "MIT",
  "description": "Reusable binary delta-update engine: apply TRDIFF10/bsdiff+zstd patch chains to a binary and discover chains from a pluggable source (OCI/GHCR or GitHub Releases). Pure Node, zero product coupling.",
  "author": "BYK",
  "homepage": "https://github.com/BYK/binpatch#readme",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/BYK/binpatch.git"
  },
  "bugs": {
    "url": "https://github.com/BYK/binpatch/issues"
  },
  "keywords": [
    "bsdiff",
    "bspatch",
    "trdiff10",
    "zstd",
    "binary",
    "delta",
    "patch",
    "update",
    "self-update",
    "oci",
    "ghcr"
  ],
  "main": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.js"
    }
  },
  "files": [
    "dist/",
    "README.md",
    "LICENSE"
  ],
  "sideEffects": false,
  "engines": {
    "node": ...
gateway · 2026-09-09 09:55:44
result
# binpatch

[![npm version](https://img.shields.io/npm/v/binpatch.svg)](https://www.npmjs.com/package/binpatch)
[![CI](https://github.com/BYK/binpatch/actions/workflows/ci.yml/badge.svg)](https://github.com/BYK/binpatch/actions)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

Reusable binary delta-update engine. Apply a **TRDIFF10 / bsdiff+zstd** patch
chain to a binary, discover chains from a pluggable source (OCI/GHCR tags or
GitHub Release assets), and generate + publish patches via a composite GitHub
Action. Pure Node, zero product coupling — works for Electron apps, CLIs,
agents, and any single-file binary artifact.

```sh
npm install binpatch
```

**Docs:** https://binpatch.p.byk.im/ · **Source:** https://github.com/BYK/binpatch

## Why

Every time your binary updates itself, your users pull the **entire file
again** — even when the new release changed a few hundred kilobytes of a
100&nbsp;MB Electron app, a 50&nbsp;MB CLI, or a 200&nbsp;MB game ...
gateway · 2026-09-09 09:56:12
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts</path>
<type>file</type>
<content>
1: /** Delta upgrade discovery and application backed by binpatch. */
2: 
3: import { join } from "node:path";
4: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
5: import * as Sentry from "@sentry/node-core/light";
6: import {
7:   applyPatchChainInMemory,
8:   extractStableChain as binpatchExtractStableChain,
9:   filterAndSortChainTags as binpatchFilterAndSortChainTags,
10:   validateChainStep as binpatchValidateChainStep,
11:   type DeltaTelemetry,
12:   type DeltaUnavailableReason,
13:   type ExtractStableChainOpts,
14:   type GitHubRelease,
15:   getPatchFromVersion,
16:   getPatchTargetSha256,
17:   ghcrSource,
18:   githubReleaseSource,
19:   type InstrumentHook,
20:   MAX_NIGHTLY_CHAIN_DEPTH,
21:   makeCache,
22:   OciClient,
23:   type OciManifest,
24: ...
gateway · 2026-09-09 09:56:40
result
/**
 * GitHub Release-asset patch source (the "stable" channel).
 *
 * Resolves a patch chain from GitHub Release assets. Each release for the
 * target platform publishes three assets:
 * - `<binaryName>`        — the binary (its digest → expected SHA-256)
 * - `<binaryName>.gz`     — gzipped binary (its size → the ratio gate)
 * - `<binaryName>.patch`  — the delta patch from the previous release
 *
 * The chain is the releases between current and target, oldest-first, capped
 * at {@link MAX_STABLE_CHAIN_DEPTH} and by {@link SIZE_THRESHOLD_RATIO}.
 *
 * All product specifics (owner/repo, binary name, user-agent, fetch) are
 * injected. Generalized from Lore's stable-channel resolver.
 */

import {
  type InstrumentHook,
  MAX_STABLE_CHAIN_DEPTH,
  type PatchChain,
  type PatchLink,
  SIZE_THRESHOLD_RATIO,
} from "../contract";
import type { SourceStrategy } from "../discover";

const SHA256_DIGEST_PATTERN = /^sha256:([0-9a-f]+)$/i;

export type GitHubAsset = {
  name: string;
  ...
gateway · 2026-09-09 09:57:08
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/AGENTS.md</path>
<type>file</type>
<content>
1: # AGENTS.md
2: 
3: Guidelines for AI agents working in this codebase.
4: 
5: ## Project Overview
6: 
7: **Sentry CLI** is a command-line interface for [Sentry](https://sentry.io), built with Node.js, [pnpm](https://pnpm.io), and [Stricli](https://bloomberg.github.io/stricli/). It lives in `packages/cli` of a pnpm workspace; the docs site lives in `apps/cli-docs`. ...
gateway · 2026-09-09 09:58:41
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Unit Tests for Delta Upgrade Module
3:  *
4:  * Tests the exported pure-computation functions that drive chain resolution
5:  * for both stable (GitHub Releases) and nightly (GHCR) channels, plus
6:  * async orchestration functions tested via fetch mocking.
7:  */
8: 
9: import { createHash } from "node:crypto";
10: import { existsSync, unlinkSync } from "node:fs";
11: import { access, readFile } from "node:fs/promises";
12: import { tmpdir } from "node:os";
13: import { join } from "node:path";
14: import { afterEach, beforeEach, describe, expect, test } from "vitest";
15: import { getPlatformBinaryName } from "../../src/lib/binary.js";
16: import {
17:   applyPatchChain,
18:   attemptDeltaUpgrade,
19:   canAttemptDelta,
20:   downloadStablePatch,
21:   type ...
gateway · 2026-09-09 09:59:00
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
1050:     const chain = await resolveStableChain("0.13.0", "0.14.0");
1051:     expect(chain).toBeNull();
1052:   });
1053: 
1054:   test("returns null when chain depth exceeds stable limit", async () => {
1055:     const binaryName = getPlatformBinaryName();
1056:     // 15 releases = 14 hops, exceeds MAX_STABLE_CHAIN_DEPTH (10)
1057:     const versions = Array.from({ length: 15 }, (_, i) => `0.${i + 1}.0`);
1058:     versions.reverse(); // newest first
1059:     const releases = versions.map((v) =>
1060:       makeRelease(v, [
1061:         makeAsset({ name: binaryName, digest: `sha256:${versionHex(v)}` }),
1062:         makeAsset({
1063:           name: `${binaryName}.patch`,
1064:           size: 100,
1065:           browser_download_url: `https://example.com/${v}.patch`,
1066:         ...
gateway · 2026-09-09 10:01:36
result
Found 17 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:
  Line 140:  * @throws {UpgradeError} When no cached version is available

  Line 150:       "No cached version available. Run any command to trigger a background version check, then retry."

  Line 181:     // Channel switching with --offline is not supported: the cached version

  Line 186:         "Cannot switch channels in offline mode — the cached version belongs to the current channel. " +

  Line 190:     // Read the cached version BEFORE persisting the channel — setReleaseChannel

  Line 194:     log.info(`Offline mode: using cached target ${target}`);

  Line 202:     const resolved = await resolveTargetVersion(resolveOpts);

  Line 219:       log.warn("Network unavailable, falling back to cached upgrade target");

  Line 220:       log.info(`Using cached target: ${target}`);

  Line 221:       return { kind: ...
gateway · 2026-09-09 10:01:47
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
110:  * @returns `{ channel, versionArg }` where versionArg is undefined when the
111:  *   positional was a channel name (so we resolve to latest) or was omitted.
112:  */
113: function resolveChannelAndVersion(positional: string | undefined): {
114:   channel: ReleaseChannel;
115:   versionArg: string | undefined;
116: } {
117:   // "nightly" and "stable" as positional args select the channel rather than
118:   // installing a specific version. Match case-insensitively for convenience.
119:   const lower = positional?.toLowerCase();
120:   if (lower === "nightly" || lower === "stable") {
121:     return {
122:       channel: lower,
123:       versionArg: undefined,
124:     };
125:   }
126: 
127:   return {
128:     channel: getReleaseChannel(),
129:     versionArg: positional,
130:   };
131: }
132: ...
gateway · 2026-09-09 10:01:55
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
270:  *
271:  * - `target`: the version string to upgrade/downgrade to (proceed with upgrade)
272:  * - `UpgradeResult`: structured result when no upgrade should proceed
273:  *   (check-only mode, or already up to date)
274:  */
275: type ResolveResult =
276:   | { kind: "target"; target: string }
277:   | { kind: "done"; result: UpgradeResult };
278: 
279: /**
280:  * Resolve the target version and handle check-only mode.
281:  *
282:  * @returns A `ResolveResult` indicating whether to proceed with the upgrade
283:  *   or return a completed result immediately. ...
gateway · 2026-09-09 10:02:05
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
80: /**
81:  * Absolute legacy install directories for the given home. See
82:  * {@link LEGACY_INSTALL_SUBDIRS} for why this is scoped to pre-XDG locations.
83:  */
84: export function getLegacyInstallDirs(homeDir: string): string[] {
85:   return LEGACY_INSTALL_SUBDIRS.map((dir) => join(homeDir, dir));
86: }
87: 
88: /**
89:  * How the CLI was installed. Determines the upgrade strategy.
90:  *
91:  * Defined here (alongside other installation constants like
92:  * {@link KNOWN_CURL_DIRS}) so that both `upgrade.ts` and
93:  * `db/install-info.ts` can import it without creating a circular
94:  * dependency. ...
gateway · 2026-09-09 10:02:13
result
Found 10 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
  Line 498: export function fetchLatestVersion(

  Line 551: export async function versionExists(

  Line 579: /** Result from downloadBinaryToTemp — includes both the binary path and lock path */

  Line 902: export async function downloadBinaryToTemp(

  Line 1030: function executeUpgradeHomebrew(): Promise<void> {

  Line 1065: function executeUpgradePackageManager(

  Line 1122: export async function executeUpgrade(

  Line 1131:       return downloadBinaryToTemp(version, downloadTag, offline, setMessage);

  Line 1133:       await executeUpgradeHomebrew();

  Line 1139:       await executeUpgradePackageManager(method, version);
gateway · 2026-09-09 10:02:22
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
1: /**
2:  * Upgrade Module
3:  *
4:  * Detects how the CLI was installed and provides self-upgrade functionality.
5:  * Binary management helpers (download URLs, locking, replacement) live in
6:  * binary.ts and are shared with the setup --install flow.
7:  */
8: 
9: import { spawn } from "node:child_process";
10: import {
11:   chmodSync,
12:   closeSync,
13:   existsSync,
14:   openSync,
15:   realpathSync,
16:   statSync,
17:   unlinkSync,
18:   writeSync,
19: } from "node:fs";
20: import { writeFile } from "node:fs/promises";
21: import { homedir } from "node:os";
22: import { dirname, isAbsolute, join, sep } from "node:path";
23: import { setTimeout } from "node:timers/promises";
24: import {
25:   acquireLock,
26:   cleanupOldBinary,
27:   determineInstallDir,
28:   fetchWithUpgradeError,
29:   ...
gateway · 2026-09-09 10:02:52
result
/**
 * Chain discovery + resolve-and-apply orchestration.
 *
 * A {@link SourceStrategy} knows how to resolve a {@link PatchChain} from some
 * backing store (an OCI registry, GitHub Release assets, ...). This module ties
 * a strategy together with the offline cache, the apply core, integrity
 * verification, and progress events — with every product-specific concern
 * (version, telemetry, logging, cache location) injected.
 */

import { applyPatchChainInMemory, parsePatchHeader } from "./bspatch";
import type { PatchCache } from "./patch-cache";
import type { DeltaResult, PatchChain } from "./contract";
import { type ProgressHandler, safeProgress } from "./events";

/**
 * A source of patch chains. Given the current and target versions, resolve the
 * ordered chain of patches (oldest hop first) plus the expected final SHA-256,
 * or `null` when no usable chain exists (caller falls back to a full download). ...
gateway · 2026-09-09 10:03:30
result
Found 45 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/binary.test.ts:
  Line 35:   resolveUpgradeSource,

  Line 38:   UPGRADE_SOURCES,

  Line 67: describe("UPGRADE_SOURCES", () => {

  Line 69:     expect(UPGRADE_SOURCES).toEqual([

  Line 84: describe("resolveUpgradeSource", () => {

  Line 88:     const resolved = await resolveUpgradeSource({

  Line 99:       source: UPGRADE_SOURCES[0],

  Line 110:     const resolved = await resolveUpgradeSource({

  Line 123:     expect(resolved.source).toBe(UPGRADE_SOURCES[1]);

  Line 136:         resolveUpgradeSource({

  Line 155:       resolveUpgradeSource({

  Line 173:       resolveUpgradeSource({


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts:
  Line 106: export type UpgradeSource = {

  Line 116: export const UPGRADE_SOURCES: readonly UpgradeSource[] = [

  ...
gateway · 2026-09-09 10:04:39
result
/**
 * binpatch — reusable binary delta-update engine.
 *
 * Two things, joined by one wire contract (see README):
 * - **apply core** — parse + apply a TRDIFF10/bsdiff patch chain to a binary.
 * - **discovery** — resolve a patch chain from a pluggable `SourceStrategy`
 *   (OCI/GHCR tags or GitHub Release assets), then apply + verify it.
 *
 * Pure Node (`node:*` builtins only), zero product coupling — the consumer
 * injects the cache directory, the download source, version comparison,
 * progress handling, and telemetry.
 */

export {
  addDiffChunk,
  applyPatch,
  applyPatchChainInMemory,
  applyPatchToMemory,
  MAX_OUTPUT_SIZE,
  offtin,
  parsePatchHeader,
  type PatchHeader,
} from "./bspatch";

export {
  type ChainMeta,
  chainFileName,
  makeCache,
  type PatchCache,
  patchFileName,
  type PatchStepMeta,
} from "./patch-cache";

// Wire-contract constants + shared chain types. ...
gateway · 2026-09-09 10:05:14
result
No files found
gateway · 2026-09-09 10:05:26
result
 M packages/cli/src/lib/binary.ts
 M packages/cli/src/lib/ghcr.ts
 M packages/cli/test/lib/binary.test.ts
 M packages/cli/test/lib/ghcr.test.ts
 M packages/cli/test/lib/install-script.test.ts
 packages/cli/src/lib/binary.ts               | 139 +++++++++++++++++++++++++--
 packages/cli/src/lib/ghcr.ts                 |  52 ++++++----
 packages/cli/test/lib/binary.test.ts         | 129 ++++++++++++++++++++++++-
 packages/cli/test/lib/ghcr.test.ts           |  30 ++++++
 packages/cli/test/lib/install-script.test.ts |  10 ++
 5 files changed, 335 insertions(+), 25 deletions(-)
diff --git a/packages/cli/src/lib/binary.ts b/packages/cli/src/lib/binary.ts
index 75582612a..bebf1da0c 100644
--- a/packages/cli/src/lib/binary.ts
+++ b/packages/cli/src/lib/binary.ts
@@ -102,6 +102,33 @@ export type InstallationMethod =
   | "yarn"
   | "unknown";
 
+/** A repository pair that hosts CLI stable releases and nightly OCI images. ...
gateway · 2026-09-09 10:05:51
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts</path>
<type>file</type>
<content>
180:   // At 0% of interval: ~0% chance
181:   // At 100% of interval: ~63% chance (1 - 1/e)
182:   // At 200% of interval: ~86% chance
183:   const probability = 1 - Math.exp(-elapsed / effectiveInterval);
184: 
185:   return Math.random() < probability;
186: }
187: 
188: /**
189:  * Check if update notifications should be suppressed for these args.
190:  */
191: export function shouldSuppressNotification(args: string[]): boolean {
192:   if (args.some((arg) => SUPPRESSED_ARGS.has(arg))) {
193:     return true;
194:   }
195:   // Suppress for "cli <subcommand>" management commands (setup, fix). ...
gateway · 2026-09-09 10:05:59
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts</path>
<type>file</type>
<content>
270:   pendingAbortController = new AbortController();
271:   const { signal } = pendingAbortController;
272: 
273:   const channel = getReleaseChannel();
274: 
275:   Sentry.startSpanManual(
276:     {
277:       name: "version-check",
278:       op: "version.check",
279:       forceTransaction: true,
280:     },
281:     async (span) => {
282:       try {
283:         // Use GHCR for nightly channel; GitHub Releases for stable.
284:         const latestVersion =
285:           channel === "nightly"
286:             ? ...
gateway · 2026-09-09 10:06:09
result
Found 10 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
  Line 137:   fetchLatestFromGitHub,

  Line 190: describe("fetchLatestFromGitHub", () => {

  Line 205:     const version = await fetchLatestFromGitHub();

  Line 223:     const version = await fetchLatestFromGitHub();

  Line 241:     const version = await fetchLatestFromGitHub();

  Line 253:     await expect(fetchLatestFromGitHub()).rejects.toThrow(UpgradeError);

  Line 254:     await expect(fetchLatestFromGitHub()).rejects.toThrow(

  Line 264:     await expect(fetchLatestFromGitHub()).rejects.toThrow(UpgradeError);

  Line 265:     await expect(fetchLatestFromGitHub()).rejects.toThrow(

  Line 279:     await expect(fetchLatestFromGitHub()).rejects.toThrow(
gateway · 2026-09-09 10:06:21
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts</path>
<type>file</type>
<content>
100:     }) as (cmd: string, args: string[], opts: object) => FakeProc,
101:   },
102: }));
103: // Initialize with the real default now that fakeProcess is defined
104: spawnImpl.fn = () => fakeProcess(0);
105: 
106: vi.mock("node:child_process", async (importOriginal) => {
107:   const orig = await importOriginal<typeof import("node:child_process")>();
108:   return {
109:     ...orig,
110:     spawn: (cmd: string, args: string[], opts: object) =>
111:       spawnImpl.fn(cmd, args, opts),
112:   };
113: });
114: 
115: // Dynamic imports: must run AFTER vi.mock() so upgrade.ts picks up the
116: // mocked spawn.
117: import { isEnoentSpawnError } from "../../src/commands/cli/upgrade.js";
118: import {
119:   acquireLock,
120:   getBinaryDownloadUrl,
121:   isNightlyVersion,
122:   releaseLock,
123: } ...
gateway · 2026-09-09 10:06:38
result
Found 3 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts:
  Line 287:             : await fetchLatestFromGitHub(signal);


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
  Line 399: export async function fetchLatestFromGitHub(

  Line 506:     ? fetchLatestFromGitHub()
gateway · 2026-09-09 10:08:53
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/binary.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Binary Management Tests
3:  *
4:  * Tests for shared binary helpers: install directory selection, paths,
5:  * download URLs, locking, and binary installation.
6:  */
7: 
8: import {
9:   chmodSync,
10:   mkdirSync,
11:   readFileSync,
12:   realpathSync,
13:   rmSync,
14:   symlinkSync,
15:   writeFileSync,
16: } from "node:fs";
17: import { access, readFile, writeFile } from "node:fs/promises";
18: import { join, sep } from "node:path";
19: import { afterEach, beforeEach, describe, expect, test } from "vitest";
20: import {
21:   acquireLock,
22:   compareVersions,
23:   determineInstallDir,
24:   fetchWithUpgradeError,
25:   getBinaryDownloadUrl,
26:   getBinaryFilename,
27:   getBinaryPaths,
28:   getGitHubReleaseByTagUrl,
29:   getLegacyInstallDirs,
30:   getPlatformBinaryName,
31:   ...
gateway · 2026-09-09 10:09:09
result
Found 46 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
  Line 640:       if (u.includes("/manifests/nightly-")) {

  Line 656:       if (u.includes("/manifests/nightly-")) {

  Line 673:       if (u.includes("/manifests/nightly-")) {

  Line 1589:   const nightlyBinDir = join(TEST_TMP_DIR, "upgrade-nightly-test");


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/patch-cache.test.ts:
  Line 337:     const chain = makeChain([patchData], "nightly-sha");

  Line 347:     expect(result?.expectedSha256).toBe("nightly-sha");


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/ghcr.test.ts:
  Line 541:       return ...
gateway · 2026-09-09 10:09:41
result
/**
 * GHCR / OCI patch source (the "nightly" channel).
 *
 * Resolves a patch chain from OCI patch-manifest tags. Patches are published
 * under `<patchTagPrefix><version>` tags whose manifests carry:
 * - annotation `from-version=<prev>` — the chain back-pointer
 * - annotation `sha256-<binaryName>=<hex>` — the target's uncompressed SHA-256
 * - a patch layer whose title is `<binaryName>.patch`
 *
 * The target binary's gzipped size (for the ratio gate) is read from the
 * target's own image manifest (its `<binaryName>.gz` layer). All product
 * specifics — registry, repo, user-agent, binary name, the version→target-tag
 * scheme, and version comparison — are injected. Generalized from Lore's
 * nightly-channel resolver.
 */

import {
  type InstrumentHook,
  MAX_NIGHTLY_CHAIN_DEPTH,
  PATCH_TAG_PREFIX,
  type PatchChain,
  type PatchLink,
  SIZE_THRESHOLD_RATIO,
} from "../contract";
import type { SourceStrategy, UnavailableReporter } from "../discover";
import { BinpatchError } ...
gateway · 2026-09-09 10:13:15
result
No files found
gateway · 2026-09-09 10:13:45
result
StatusCode: non 2xx status code (404 GET https://raw.githubusercontent.com/BYK/binpatch/v0.4.2/src/sources/github-release.ts)
gateway · 2026-09-09 10:14:10
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts</path>
<type>file</type>
<content>
1: /** Delta upgrade discovery and application backed by binpatch. */
2: 
3: import { join } from "node:path";
4: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
5: import * as Sentry from "@sentry/node-core/light";
6: import {
7:   applyPatchChainInMemory,
8:   extractStableChain as binpatchExtractStableChain,
9:   filterAndSortChainTags as binpatchFilterAndSortChainTags,
10:   validateChainStep as binpatchValidateChainStep,
11:   type DeltaTelemetry,
12:   type DeltaUnavailableReason,
13:   type ExtractStableChainOpts,
14:   type GitHubRelease,
15:   getPatchFromVersion,
16:   getPatchTargetSha256,
17:   ghcrSource,
18:   githubReleaseSource,
19:   type InstrumentHook,
20:   MAX_NIGHTLY_CHAIN_DEPTH,
21:   makeCache,
22:   OciClient,
23:   type OciManifest,
24: ...
gateway · 2026-09-09 10:14:47
result
/**
 * GitHub Release-asset patch source (the "stable" channel).
 *
 * Resolves a patch chain from GitHub Release assets. Each release for the
 * target platform publishes three assets:
 * - `<binaryName>`        — the binary (its digest → expected SHA-256)
 * - `<binaryName>.gz`     — gzipped binary (its size → the ratio gate)
 * - `<binaryName>.patch`  — the delta patch from the previous release
 *
 * The chain is the releases between current and target, oldest-first, capped
 * at {@link MAX_STABLE_CHAIN_DEPTH} and by {@link SIZE_THRESHOLD_RATIO}.
 *
 * All product specifics (owner/repo, binary name, user-agent, fetch) are
 * injected. Generalized from Lore's stable-channel resolver.
 */

import {
  type InstrumentHook,
  MAX_STABLE_CHAIN_DEPTH,
  type PatchChain,
  type PatchLink,
  SIZE_THRESHOLD_RATIO,
} from "../contract";
import type { SourceStrategy } from "../discover";

const SHA256_DIGEST_PATTERN = /^sha256:([0-9a-f]+)$/i;

export type GitHubAsset = {
  name: string;
  ...
gateway · 2026-09-09 10:15:17
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/ghcr.ts</path>
<type>file</type>
<content>
120:       // Propagate external abort immediately — don't retry caller cancellation
121:       if (isExternalAbort(lastError, externalSignal)) {
122:         break;
123:       }
124:       // Only retry on timeout or network errors — not HTTP errors
125:       if (attempt >= GHCR_MAX_RETRIES || !isRetryableError(lastError)) {
126:         break;
127:       }
128:     }
129:   }
130: 
131:   throw new UpgradeError(
132:     "network_error",
133:     `${context}: ${lastError?.message ?? "unknown error"}`
134:   );
135: }
136: 
137: /** Default GHCR repository for CLI distribution. */
138: export const GHCR_REPO = PRIMARY_UPGRADE_SOURCE.ghcrRepo;
139: 
140: /** OCI tag for nightly builds */
141: export const GHCR_TAG = "nightly";
142: 
143: /** Base URL for GHCR registry API */
144: const GHCR_REGISTRY = ...
gateway · 2026-09-09 10:15:51
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
690:   }
691: 
692:   if (writeError) {
693:     throw writeError;
694:   }
695: 
696:   if (streamError !== undefined) {
697:     throw streamError;
698:   }
699: }
700: 
701: /**
702:  * Build the gzip filename for the current platform binary.
703:  *
704:  * Nightly builds are stored in GHCR as `sentry-<os>-<arch>.gz` (or
705:  * `sentry-windows-x64.exe.gz` on Windows). This filename is the
706:  * `org.opencontainers.image.title` annotation on the matching OCI layer.
707:  *
708:  * @returns Filename of the gzip-compressed binary for this platform
709:  */
710: function getNightlyGzFilename(): string {
711:   return `${getPlatformBinaryName()}.gz`;
712: }
713: 
714: /**
715:  * Download a nightly binary from GHCR and decompress it to `destPath`. ...
gateway · 2026-09-09 10:16:13
result
[
  {
    "name": "0.4.2",
    "zipball_url": "https://api.github.com/repos/BYK/binpatch/zipball/refs/tags/0.4.2",
    "tarball_url": "https://api.github.com/repos/BYK/binpatch/tarball/refs/tags/0.4.2",
    "commit": {
      "sha": "9ba6bbb8227fcbd2521852d2311c82afac5e9573",
      "url": "https://api.github.com/repos/BYK/binpatch/commits/9ba6bbb8227fcbd2521852d2311c82afac5e9573"
    },
    "node_id": "REF_kwDOThqhQK9yZWZzL3RhZ3MvMC40LjI"
  },
  {
    "name": "0.4.1",
    "zipball_url": "https://api.github.com/repos/BYK/binpatch/zipball/refs/tags/0.4.1",
    "tarball_url": "https://api.github.com/repos/BYK/binpatch/tarball/refs/tags/0.4.1",
    "commit": {
      "sha": "d0593cdd89eb720edddf9644e0753613e4a8e622",
      "url": "https://api.github.com/repos/BYK/binpatch/commits/d0593cdd89eb720edddf9644e0753613e4a8e622"
    },
    "node_id": "REF_kwDOThqhQK9yZWZzL3RhZ3MvMC40LjE"
  },
  {
    "name": "0.4.0",
    "zipball_url": ...
gateway · 2026-09-09 10:18:18
result
Found 84 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts:
  Line 18:   attemptDeltaUpgrade,

  Line 24:   fetchRecentReleases,

  Line 32:   prefetchNightlyPatches,

  Line 33:   prefetchStablePatches,

  Line 34:   resolveNightlyChain,

  Line 35:   resolveNightlyDelta,

  Line 36:   resolveStableChain,

  Line 37:   resolveStableDelta,

  Line 817: // fetchRecentReleases

  Line 819: describe("fetchRecentReleases", () => {

  Line 834:     const result = await fetchRecentReleases();

  Line 842:     const result = await fetchRecentReleases();

  Line 851:     const result = await fetchRecentReleases();

  Line 891: // resolveStableChain (async orchestrator)

  Line 893: describe("resolveStableChain", () => {

  Line 947:     const chain = await resolveStableChain("0.13.0", "0.14.0");

  Line 1000:     const chain = await resolveStableChain("0.13.0", "0.15.0");

  Line 1018:   ...
gateway · 2026-09-09 10:19:34
result
{
  "url": "https://api.github.com/repos/getsentry/cli/issues/1244",
  "repository_url": "https://api.github.com/repos/getsentry/cli",
  "labels_url": "https://api.github.com/repos/getsentry/cli/issues/1244/labels{/name}",
  "comments_url": "https://api.github.com/repos/getsentry/cli/issues/1244/comments",
  "events_url": "https://api.github.com/repos/getsentry/cli/issues/1244/events",
  "html_url": "https://github.com/getsentry/cli/issues/1244",
  "id": 4890976993,
  "node_id": "I_kwDOQm6jAs8AAAABI4Zi4Q",
  "number": 1244,
  "title": "toolkit merge: bridge CLI release + dual-source upgrade compatibility",
  "user": {
    "login": "BYK",
    "id": 126780,
    "node_id": "MDQ6VXNlcjEyNjc4MA==",
    "avatar_url": "https://avatars.githubusercontent.com/u/126780?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/BYK",
    "html_url": "https://github.com/BYK",
    "followers_url": "https://api.github.com/users/BYK/followers",
    "following_url": ...
gateway · 2026-09-09 10:20:43
result
[
  {
    "url": "https://api.github.com/repos/getsentry/cli/issues/comments/4978828102",
    "html_url": "https://github.com/getsentry/cli/issues/1244#issuecomment-4978828102",
    "issue_url": "https://api.github.com/repos/getsentry/cli/issues/1244",
    "id": 4978828102,
    "node_id": "IC_kwDOQm6jAs8AAAABKMLjRg",
    "user": {
      "login": "BYK",
      "id": 126780,
      "node_id": "MDQ6VXNlcjEyNjc4MA==",
      "avatar_url": "https://avatars.githubusercontent.com/u/126780?v=4",
      "gravatar_id": "",
      "url": "https://api.github.com/users/BYK",
      "html_url": "https://github.com/BYK",
      "followers_url": "https://api.github.com/users/BYK/followers",
      "following_url": "https://api.github.com/users/BYK/following{/other_user}",
      "gists_url": "https://api.github.com/users/BYK/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/BYK/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/BYK/subscriptions",
      ...
gateway · 2026-09-09 10:22:22
result
diff --git a/packages/cli/src/lib/ghcr.ts b/packages/cli/src/lib/ghcr.ts
index 43d6deb7e..f648ab78a 100644
--- a/packages/cli/src/lib/ghcr.ts
+++ b/packages/cli/src/lib/ghcr.ts
@@ -20,6 +20,10 @@
 import { getUserAgent } from "./constants.js";
 import { customFetch } from "./custom-ca.js";
 import { UpgradeError } from "./errors.js";
+import {
+  PRIMARY_UPGRADE_SOURCE,
+  type UpgradeSource,
+} from "./binary.js";
 
 /** Default timeout for GHCR HTTP requests (10 seconds) */
 const GHCR_REQUEST_TIMEOUT = 10_000;
@@ -130,8 +134,8 @@ async function fetchWithRetry(
   );
 }
 
-/** GHCR repository for CLI distribution */
-export const GHCR_REPO = "getsentry/cli";
+/** Default GHCR repository for CLI distribution. */
+export const GHCR_REPO = PRIMARY_UPGRADE_SOURCE.ghcrRepo;
 
 /** OCI tag for nightly builds */
 export const GHCR_TAG = "nightly";
@@ -189,13 +193,20 @@ export type OciManifest = {
  * @returns Bearer token string
  * @throws {UpgradeError} On network failure or malformed ...
gateway · 2026-09-09 10:22:53
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
88: /**
89:  * How the CLI was installed. Determines the upgrade strategy.
90:  *
91:  * Defined here (alongside other installation constants like
92:  * {@link KNOWN_CURL_DIRS}) so that both `upgrade.ts` and
93:  * `db/install-info.ts` can import it without creating a circular
94:  * dependency.
95:  */
96: export type InstallationMethod =
97:   | "curl"
98:   | "brew"
99:   | "npm"
100:   | "pnpm"
101:   | "bun"
102:   | "yarn"
103:   | "unknown";
104: 
105: /** A repository pair that hosts CLI stable releases and nightly OCI images. */
106: export type UpgradeSource = {
107:   /** GitHub `owner/repository` containing CLI release assets. */
108:   readonly githubRepo: string;
109:   /** GHCR `owner/package` containing CLI nightly images and delta patches. ...
gateway · 2026-09-09 10:23:23
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts</path>
<type>file</type>
<content>
180:   // At 0% of interval: ~0% chance
181:   // At 100% of interval: ~63% chance (1 - 1/e)
182:   // At 200% of interval: ~86% chance
183:   const probability = 1 - Math.exp(-elapsed / effectiveInterval);
184: 
185:   return Math.random() < probability;
186: }
187: 
188: /**
189:  * Check if update notifications should be suppressed for these args.
190:  */
191: export function shouldSuppressNotification(args: string[]): boolean {
192:   if (args.some((arg) => SUPPRESSED_ARGS.has(arg))) {
193:     return true;
194:   }
195:   // Suppress for "cli <subcommand>" management commands (setup, fix). ...
gateway · 2026-09-09 10:23:56
result
Found 28 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts:
  Line 106: export type UpgradeSource = {

  Line 112:   readonly tagPrefix: string;

  Line 116: export const UPGRADE_SOURCES: readonly UpgradeSource[] = [

  Line 120:     tagPrefix: "cli@",

  Line 125:     tagPrefix: "",

  Line 236:   source: UpgradeSource = PRIMARY_UPGRADE_SOURCE

  Line 238:   const tag = `${source.tagPrefix}${version}`;

  Line 244:   source: UpgradeSource = PRIMARY_UPGRADE_SOURCE

  Line 252:   source: UpgradeSource = PRIMARY_UPGRADE_SOURCE

  Line 254:   const tag = `${source.tagPrefix}${version}`;

  Line 260:   source: UpgradeSource = PRIMARY_UPGRADE_SOURCE

  Line 262:   return source.tagPrefix

  Line 269:   source: UpgradeSource = PRIMARY_UPGRADE_SOURCE

  Line 278: export type ResolvedUpgradeSource = {

  Line 280:   readonly source: UpgradeSource;

  Line 286: export type ResolveUpgradeSourceOptions ...
gateway · 2026-09-09 10:24:07
result
No files found
gateway · 2026-09-09 10:24:15
result
Found 8 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
  Line 766:   const url = getBinaryDownloadUrl(version);


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts:
  Line 116: export const UPGRADE_SOURCES: readonly UpgradeSource[] = [

  Line 130: export const PRIMARY_UPGRADE_SOURCE = UPGRADE_SOURCES[0];

  Line 234: export function getBinaryDownloadUrl(

  Line 250: export function getGitHubReleaseByTagUrl(

  Line 259: export function getGitHubLatestReleaseUrl(

  Line 268: export function getGitHubRepositoryUrl(

  Line 306:   for (const source of UPGRADE_SOURCES) {
gateway · 2026-09-09 10:24:23
result
Found 17 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/binary.test.ts:
  Line 28:   getGitHubReleaseByTagUrl,

  Line 35:   resolveUpgradeSource,

  Line 84: describe("resolveUpgradeSource", () => {

  Line 88:     const resolved = await resolveUpgradeSource({

  Line 89:       getProbeUrl: (source) => getGitHubReleaseByTagUrl("0.45.0", source),

  Line 110:     const resolved = await resolveUpgradeSource({

  Line 111:       getProbeUrl: (source) => getGitHubReleaseByTagUrl("0.45.0", source),

  Line 136:         resolveUpgradeSource({

  Line 137:           getProbeUrl: (source) => getGitHubReleaseByTagUrl("0.45.0", source),

  Line 155:       resolveUpgradeSource({

  Line 156:         getProbeUrl: (source) => getGitHubReleaseByTagUrl("0.45.0", source),

  Line 173:       resolveUpgradeSource({

  Line 174:         getProbeUrl: (source) => getGitHubReleaseByTagUrl("0.45.0", ...
gateway · 2026-09-09 10:25:22
result
/**
 * binpatch — reusable binary delta-update engine.
 *
 * Two things, joined by one wire contract (see README):
 * - **apply core** — parse + apply a TRDIFF10/bsdiff patch chain to a binary.
 * - **discovery** — resolve a patch chain from a pluggable `SourceStrategy`
 *   (OCI/GHCR tags or GitHub Release assets), then apply + verify it.
 *
 * Pure Node (`node:*` builtins only), zero product coupling — the consumer
 * injects the cache directory, the download source, version comparison,
 * progress handling, and telemetry.
 */

export {
  addDiffChunk,
  applyPatch,
  applyPatchChainInMemory,
  applyPatchToMemory,
  MAX_OUTPUT_SIZE,
  offtin,
  parsePatchHeader,
  type PatchHeader,
} from "./bspatch";

export {
  type ChainMeta,
  chainFileName,
  makeCache,
  type PatchCache,
  patchFileName,
  type PatchStepMeta,
} from "./patch-cache";

// Wire-contract constants + shared chain types. ...
gateway · 2026-09-09 10:25:52
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade</path>
<type>directory</type>
<entries>
.craft.yml
.git
.github/
.gitignore
.lore.md
.nojekyll
.npmrc
AGENTS.md
apps/
CHANGELOG.md
codemods/
LICENSE.md
node_modules/
package.json
packages/
pnpm-lock.yaml
pnpm-workspace.yaml
README.md

(18 entries)
</entries>
gateway · 2026-09-09 10:26:31
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/AGENTS.md</path>
<type>file</type>
<content>
1: # AGENTS.md
2: 
3: Guidelines for AI agents working in this codebase.
4: 
5: ## Project Overview
6: 
7: **Sentry CLI** is a command-line interface for [Sentry](https://sentry.io), built with Node.js, [pnpm](https://pnpm.io), and [Stricli](https://bloomberg.github.io/stricli/). It lives in `packages/cli` of a pnpm workspace; the docs site lives in `apps/cli-docs`. ...
gateway · 2026-09-09 10:26:57

I’m tracing the selected-source path into the delta entry points and checking the exact 0.4.2 public contracts before I give file- and symbol-level recommendations. I’ll keep this read-only and won’t run broad tests.

gpt-5.6-sol · 2026-09-09 10:26:57 · ~47 tokens
result
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts:
  Line 14: import { getReleaseChannel } from "./db/release-channel.js";

  Line 16:   getVersionCheckInfo,

  Line 18:   setVersionCheckInfo,

  Line 167:   const { lastChecked } = getVersionCheckInfo();

  Line 216: export function abortPendingVersionCheck(): void {

  Line 228:   channel: "stable" | "nightly",

  Line 229:   latestVersion: string,

  Line 232:   if (semverCompare(latestVersion, CLI_VERSION) !== 1) {

  Line 236:     if (channel === "nightly") {

  Line 237:       await prefetchNightlyPatches(latestVersion, signal);

  Line 239:       await prefetchStablePatches(latestVersion, signal);

  Line 259: function checkForUpdateInBackgroundImpl(): void {

  Line 273:   const channel = getReleaseChannel();

  Line 283:         // Use GHCR for nightly channel; GitHub Releases for stable. ...
gateway · 2026-09-09 10:27:08
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
1: /**
2:  * Upgrade Module
3:  *
4:  * Detects how the CLI was installed and provides self-upgrade functionality.
5:  * Binary management helpers (download URLs, locking, replacement) live in
6:  * binary.ts and are shared with the setup --install flow.
7:  */
8: 
9: import { spawn } from "node:child_process";
10: import {
11:   chmodSync,
12:   closeSync,
13:   existsSync,
14:   openSync,
15:   realpathSync,
16:   statSync,
17:   unlinkSync,
18:   writeSync,
19: } from "node:fs";
20: import { writeFile } from "node:fs/promises";
21: import { homedir } from "node:os";
22: import { dirname, isAbsolute, join, sep } from "node:path";
23: import { setTimeout } from "node:timers/promises";
24: import {
25:   acquireLock,
26:   cleanupOldBinary,
27:   determineInstallDir,
28:   fetchWithUpgradeError,
29:   ...
gateway · 2026-09-09 10:27:56
result
 M packages/cli/src/lib/binary.ts
 M packages/cli/src/lib/ghcr.ts
 M packages/cli/test/lib/binary.test.ts
 M packages/cli/test/lib/ghcr.test.ts
 M packages/cli/test/lib/install-script.test.ts
 packages/cli/src/lib/binary.ts               | 139 +++++++++++++++++++++++++--
 packages/cli/src/lib/ghcr.ts                 |  52 ++++++----
 packages/cli/test/lib/binary.test.ts         | 129 ++++++++++++++++++++++++-
 packages/cli/test/lib/ghcr.test.ts           |  30 ++++++
 packages/cli/test/lib/install-script.test.ts |  10 ++
 5 files changed, 335 insertions(+), 25 deletions(-)
gateway · 2026-09-09 10:28:04
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Unit Tests for Delta Upgrade Module
3:  *
4:  * Tests the exported pure-computation functions that drive chain resolution
5:  * for both stable (GitHub Releases) and nightly (GHCR) channels, plus
6:  * async orchestration functions tested via fetch mocking.
7:  */
8: 
9: import { createHash } from "node:crypto";
10: import { existsSync, unlinkSync } from "node:fs";
11: import { access, readFile } from "node:fs/promises";
12: import { tmpdir } from "node:os";
13: import { join } from "node:path";
14: import { afterEach, beforeEach, describe, expect, test } from "vitest";
15: import { getPlatformBinaryName } from "../../src/lib/binary.js";
16: import {
17:   applyPatchChain,
18:   attemptDeltaUpgrade,
19:   canAttemptDelta,
20:   downloadStablePatch,
21:   type ...
gateway · 2026-09-09 10:28:13
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.mocked.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Integration tests for delta upgrade orchestration with a non-dev CLI_VERSION.
3:  *
4:  * These tests use `vi.mock()` to override `CLI_VERSION` from constants.js
5:  * so that `canAttemptDelta()` passes its dev-build guard (the real `CLI_VERSION`
6:  * is "0.0.0-dev" in test mode, which short-circuits the orchestrator).
7:  *
8:  * Kept as a sibling file to `delta-upgrade.test.ts` because its
9:  * `vi.mock()` would invert the assumptions of the dev-mode null-return
10:  * tests in that file. Under `bun test --isolate` each file gets a fresh
11:  * module graph, so the mocks here don't leak. ...
gateway · 2026-09-09 10:28:30
result
/**
 * Chain discovery + resolve-and-apply orchestration.
 *
 * A {@link SourceStrategy} knows how to resolve a {@link PatchChain} from some
 * backing store (an OCI registry, GitHub Release assets, ...). This module ties
 * a strategy together with the offline cache, the apply core, integrity
 * verification, and progress events — with every product-specific concern
 * (version, telemetry, logging, cache location) injected.
 */

import { applyPatchChainInMemory, parsePatchHeader } from "./bspatch";
import type { PatchCache } from "./patch-cache";
import type { DeltaResult, PatchChain } from "./contract";
import { type ProgressHandler, safeProgress } from "./events";

/**
 * A source of patch chains. Given the current and target versions, resolve the
 * ordered chain of patches (oldest hop first) plus the expected final SHA-256,
 * or `null` when no usable chain exists (caller falls back to a full download). ...
gateway · 2026-09-09 10:29:58
result
Found 35 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/pnpm-lock.yaml:
  Line 867:   '@hono/mcp@0.2.5':

  Line 1548:   '@sentry/cli@2.58.6':

  Line 4207:   trpc-cli@0.12.4:

  Line 5355:   '@hono/mcp@0.2.5(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(hono-rate-limiter@0.4.2(hono@4.12.34))(hono@4.12.34)(zod@4.4.3)':

  Line 6000:   '@sentry/cli@2.58.6':

  Line 9255:   trpc-cli@0.12.4(@trpc/server@11.18.0(typescript@5.9.3))(valibot@1.4.2(typescript@5.9.3))(zod@4.4.3):


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/apps/cli-docs/src/fragments/commands/issue.md:
  Line 220: sentry issue resolve CLI-G5 --in @commit:getsentry/cli@abc123def


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/binary.test.ts:
  Line 46:     expect(url).toContain("/cli@1.0.0/");

  Line 73:         ...
gateway · 2026-09-09 12:55:20
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts</path>
<type>file</type>
<content>
1: /** Delta upgrade discovery and application backed by binpatch. */
2: 
3: import { join } from "node:path";
4: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
5: import * as Sentry from "@sentry/node-core/light";
6: import {
7:   applyPatchChainInMemory,
8:   extractStableChain as binpatchExtractStableChain,
9:   filterAndSortChainTags as binpatchFilterAndSortChainTags,
10:   validateChainStep as binpatchValidateChainStep,
11:   type DeltaTelemetry,
12:   type DeltaUnavailableReason,
13:   type ExtractStableChainOpts,
14:   type GitHubRelease,
15:   getPatchFromVersion,
16:   getPatchTargetSha256,
17:   ghcrSource,
18:   githubReleaseSource,
19:   type InstrumentHook,
20:   MAX_NIGHTLY_CHAIN_DEPTH,
21:   makeCache,
22:   OciClient,
23:   type OciManifest,
24: ...
gateway · 2026-09-09 12:55:31
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts</path>
<type>file</type>
<content>
220:     currentVersion,
221:     targetVersion,
222:     compareVersions
223:   );
224: }
225: 
226: type ChainStepResult =
227:   | { ok: true; digest: string; size: number }
228:   | {
229:       ok: false;
230:       failure:
231:         | {
232:             reason: "version-mismatch";
233:             expected: string;
234:             actual: string | null;
235:           }
236:         | { reason: "missing-layer"; layerName: string }
237:         | { reason: "size-exceeded"; layerSize: number; budget: number };
238:     };
239: 
240: export function validateChainStep(
241:   manifest: OciManifest,
242:   opts: { expectedFrom: string; patchLayerName: string; sizeLimit: number }
243: ): ChainStepResult {
244:   const fromVersion = getPatchFromVersion(manifest);
245:   if (fromVersion !== ...
gateway · 2026-09-09 12:55:49
result
/**
 * GitHub Release-asset patch source (the "stable" channel).
 *
 * Resolves a patch chain from GitHub Release assets. Each release for the
 * target platform publishes three assets:
 * - `<binaryName>`        — the binary (its digest → expected SHA-256)
 * - `<binaryName>.gz`     — gzipped binary (its size → the ratio gate)
 * - `<binaryName>.patch`  — the delta patch from the previous release
 *
 * The chain is the releases between current and target, oldest-first, capped
 * at {@link MAX_STABLE_CHAIN_DEPTH} and by {@link SIZE_THRESHOLD_RATIO}.
 *
 * All product specifics (owner/repo, binary name, user-agent, fetch) are
 * injected. Generalized from Lore's stable-channel resolver.
 */

import {
  type InstrumentHook,
  MAX_STABLE_CHAIN_DEPTH,
  type PatchChain,
  type PatchLink,
  SIZE_THRESHOLD_RATIO,
} from "../contract";
import type { SourceStrategy } from "../discover";

const SHA256_DIGEST_PATTERN = /^sha256:([0-9a-f]+)$/i;

export type GitHubAsset = {
  name: string;
  ...
gateway · 2026-09-09 12:57:04
result
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/install-script.test.ts:
  Line 20: import { UPGRADE_SOURCES } from "../../src/lib/binary.js";

  Line 83:   https://api.github.com/repos/getsentry/toolkit/releases\\?per_page=100)

  Line 88:       *) body='[{"tag_name":"mcp@9.0.0"},{"tag_name":"cli@0.51.0-dev.1","prerelease":true},{"tag_name":"cli@0.50.0"}]' ;;

  Line 91:   https://api.github.com/repos/getsentry/cli/releases/latest)

  Line 94:   https://api.github.com/repos/getsentry/toolkit/releases/tags/cli%40*)

  Line 99:       *) body='{"tag_name":"cli@0.31.0"}' ;;

  Line 102:   https://api.github.com/repos/getsentry/cli/releases/tags/*)

  Line 105:   https://api.github.com/repos/getsentry/toolkit)

  Line 109:       body='{"full_name":"getsentry/toolkit"}'

  Line 112:   https://api.github.com/repos/getsentry/cli)

  Line 113:     ...
gateway · 2026-09-09 12:57:47
result
...output truncated...

Full output saved to: /home/byk/.local/share/opencode/tool-output/tool_0863ef578001C7hRc8627Nyeti

   isDowngrade,
   isNightlyVersion,
+  PRIMARY_UPGRADE_SOURCE,
+  type UpgradeSource,
 } from "./binary.js";
 import { CLI_VERSION } from "./constants.js";
 import { customFetch } from "./custom-ca.js";
 import { getConfigDir } from "./db/index.js";
 import { formatBytes } from "./formatters/numbers.js";
-import { GHCR_REPO } from "./ghcr.js";
 import { logger } from "./logger.js";
 import { makeByteProgress, type SetMessage } from "./progress.js";
 import { withTracing, withTracingSpan } from "./telemetry.js";
@@ -68,11 +69,15 @@ export type DeltaResult = {
   chainLength: number;
 };
 
-// GHCR publishes nightlies to ghcr.io/getsentry/cli (see src/lib/ghcr.ts
-// GHCR_REPO). Importing as a named import keeps a single source of truth and
-// avoids the silent 404 introduced when this was a string literal.
 const log = logger.withTag("delta-upgrade");
 
+function ...
gateway · 2026-09-09 12:59:01
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
274: /** GitHub API base URL for the primary release source. */
275: export const GITHUB_RELEASES_URL = getGitHubReleasesUrl();
276: 
277: /** Result of selecting one source for an upgrade operation. */
278: export type ResolvedUpgradeSource = {
279:   /** The selected release source. */
280:   readonly source: UpgradeSource;
281:   /** The successful response from the source probe. */
282:   readonly response: Response;
283: };
284: 
285: /** Configuration for selecting the first available upgrade source. */
286: export type ResolveUpgradeSourceOptions = {
287:   /** Build the source-specific URL whose response proves source availability. */
288:   readonly getProbeUrl: (source: UpgradeSource) => string;
289:   /** Fetch implementation used for the probe. Defaults to the CLI CA-aware fetch. ...
gateway · 2026-09-09 13:00:33
result
Found 79 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts:
  Line 263:     ? `${getGitHubReleasesUrl(source)}?per_page=100`


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/api/traces.ts:
  Line 31:   API_MAX_PER_PAGE,

  Line 445:  * When `limit` exceeds {@link API_MAX_PER_PAGE}, transparently fetches multiple

  Line 582:  * When `limit` exceeds {@link API_MAX_PER_PAGE}, transparently fetches multiple


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/api/repositories.ts:
  Line 14:   API_MAX_PER_PAGE,

  Line 94:         perPage: API_MAX_PER_PAGE,

  Line 96:     MAX_PAGINATION_PAGES * ...
gateway · 2026-09-09 13:00:41
result
Found 35 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:
  Line 58:   resolveExistingUpgradeVersion,

  Line 59:   resolveLatestUpgradeVersion,

  Line 182:       source?: UpgradeSource;

  Line 218:       source: resolved.source,

  Line 289:   | { kind: "target"; target: string; source?: UpgradeSource }

  Line 290:   | { kind: "done"; result: UpgradeResult; source?: UpgradeSource };

  Line 305:   const resolved = await resolveExistingUpgradeVersion(target);

  Line 309:   return resolved.source;

  Line 325:     ? await resolveLatestUpgradeVersion(channel)

  Line 331:   let source = latestResolution?.source;

  Line 343:       source: latestResolution?.source,

  Line 367:     source = (await resolvePinnedVersion(lookupMethod, target)) ?? source;

  Line 370:   return { kind: "target", target, source };

  Line 656:   source?: UpgradeSource;

  Line 669:     source,

  Line ...
gateway · 2026-09-09 13:00:58
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
36: } from "../../lib/db/release-channel.js";
37: import { getVersionCheckInfo } from "../../lib/db/version-check.js";
38: import { UpgradeError } from "../../lib/errors.js";
39: import { formatUpgradeResult } from "../../lib/formatters/human.js";
40: import { formatBytes } from "../../lib/formatters/numbers.js";
41: import { CommandOutput } from "../../lib/formatters/output.js";
42: import { logger } from "../../lib/logger.js";
43: import { withProgress } from "../../lib/polling.js";
44: import {
45:   type ChangelogSummary,
46:   fetchChangelog,
47: } from "../../lib/release-notes.js";
48: import { isInPath } from "../../lib/shell.js";
49: import {
50:   detectInstallationMethod,
51:   executeUpgrade,
52:   fetchLatestVersion,
53:   getCurlInstallPaths,
54:   type InstallationMethod,
55:   ...
gateway · 2026-09-09 13:02:24
result
import { afterEach, describe, expect, it, vi } from "vitest";
import {
  type InstrumentHook,
  extractSha256,
  extractStableChain,
  filterAndSortChainTags,
  getPatchFromVersion,
  getPatchTargetSha256,
  ghcrSource,
  type GitHubRelease,
  githubReleaseSource,
  getStableTargetSha256,
  OciClient,
  type OciManifest,
  validateChainStep,
} from "../src";

// Build a JSON Response for mocked fetch calls.
function json(body: unknown): Response {
  return new Response(JSON.stringify(body), {
    status: 200,
    headers: { "content-type": "application/json" },
  });
}

// A semver-ish comparator matching the gateway's compareVersions contract
// (returns -1 | 0 | 1) for the nightly tag-ordering tests.
function cmp(a: string, b: string): -1 | 0 | 1 {
  const pa = a.split(".").map(Number);
  const pb = b.split(".").map(Number);
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
    const x = pa[i] ?? 0;
    const y = pb[i] ?? ...
gateway · 2026-09-09 13:08:12
result
/**
 * GitHub Release-asset patch source (the "stable" channel).
 *
 * Resolves a patch chain from GitHub Release assets. Each release for the
 * target platform publishes three assets:
 * - `<binaryName>`        — the binary (its digest → expected SHA-256)
 * - `<binaryName>.gz`     — gzipped binary (its size → the ratio gate)
 * - `<binaryName>.patch`  — the delta patch from the previous release
 *
 * The chain is the releases between current and target, oldest-first, capped
 * at {@link MAX_STABLE_CHAIN_DEPTH} and by {@link SIZE_THRESHOLD_RATIO}.
 *
 * All product specifics (owner/repo, binary name, user-agent, fetch) are
 * injected. Generalized from Lore's stable-channel resolver.
 */

import {
  type InstrumentHook,
  MAX_STABLE_CHAIN_DEPTH,
  type PatchChain,
  type PatchLink,
  SIZE_THRESHOLD_RATIO,
} from "../contract";
import type { SourceStrategy } from "../discover";

const SHA256_DIGEST_PATTERN = /^sha256:([0-9a-f]+)$/i;

export type GitHubAsset = {
  name: string;
  ...
gateway · 2026-09-09 13:08:21
result
/**
 * GHCR / OCI patch source (the "nightly" channel).
 *
 * Resolves a patch chain from OCI patch-manifest tags. Patches are published
 * under `<patchTagPrefix><version>` tags whose manifests carry:
 * - annotation `from-version=<prev>` — the chain back-pointer
 * - annotation `sha256-<binaryName>=<hex>` — the target's uncompressed SHA-256
 * - a patch layer whose title is `<binaryName>.patch`
 *
 * The target binary's gzipped size (for the ratio gate) is read from the
 * target's own image manifest (its `<binaryName>.gz` layer). All product
 * specifics — registry, repo, user-agent, binary name, the version→target-tag
 * scheme, and version comparison — are injected. Generalized from Lore's
 * nightly-channel resolver.
 */

import {
  type InstrumentHook,
  MAX_NIGHTLY_CHAIN_DEPTH,
  PATCH_TAG_PREFIX,
  type PatchChain,
  type PatchLink,
  SIZE_THRESHOLD_RATIO,
} from "../contract";
import type { SourceStrategy, UnavailableReporter } from "../discover";
import { BinpatchError } ...
gateway · 2026-09-09 13:08:30
result
/**
 * OCI (GHCR-style) anonymous-pull client.
 *
 * Encapsulates the OCI download protocol for fetching binaries and patch
 * artifacts from a container registry (ghcr.io by default). Anonymous,
 * read-only: performs the standard token exchange, fetches manifests, lists
 * tags, and downloads blobs.
 *
 * Registry / repository / user-agent are all injected — no product coupling.
 * Generalized from Lore's `ghcr.ts`.
 *
 * Redirect quirk: ghcr.io blob downloads return a 307 to Azure Blob Storage.
 * Following the redirect automatically would forward the Authorization header
 * to Azure (→ 404), so redirects are followed manually WITHOUT the auth header.
 */

import { BinpatchError } from "../errors";

/** Default timeout for registry metadata requests (10s). */
const REQUEST_TIMEOUT = 10_000;

/** Retry attempts for transient failures. */
const MAX_RETRIES = 1;

/** Timeout for (larger) blob downloads (30s). */
const BLOB_TIMEOUT = 30_000;

/** Page size for tag-listing pagination. ...
gateway · 2026-09-09 13:09:00
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts</path>
<type>file</type>
<content>
1: /** Delta upgrade discovery and application backed by binpatch. */
2: 
3: import { join } from "node:path";
4: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
5: import * as Sentry from "@sentry/node-core/light";
6: import {
7:   applyPatchChainInMemory,
8:   extractStableChain as binpatchExtractStableChain,
9:   filterAndSortChainTags as binpatchFilterAndSortChainTags,
10:   validateChainStep as binpatchValidateChainStep,
11:   type DeltaTelemetry,
12:   type DeltaUnavailableReason,
13:   type ExtractStableChainOpts,
14:   type GitHubRelease,
15:   getPatchFromVersion,
16:   getPatchTargetSha256,
17:   ghcrSource,
18:   githubReleaseSource,
19:   type InstrumentHook,
20:   MAX_NIGHTLY_CHAIN_DEPTH,
21:   makeCache,
22:   OciClient,
23:   type OciManifest,
24: ...
gateway · 2026-09-09 13:10:18
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.mocked.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Integration tests for delta upgrade orchestration with a non-dev CLI_VERSION.
3:  *
4:  * These tests use `vi.mock()` to override `CLI_VERSION` from constants.js
5:  * so that `canAttemptDelta()` passes its dev-build guard (the real `CLI_VERSION`
6:  * is "0.0.0-dev" in test mode, which short-circuits the orchestrator).
7:  *
8:  * Kept as a sibling file to `delta-upgrade.test.ts` because its
9:  * `vi.mock()` would invert the assumptions of the dev-mode null-return
10:  * tests in that file. Under `bun test --isolate` each file gets a fresh
11:  * module graph, so the mocks here don't leak. ...
gateway · 2026-09-09 13:11:19
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
90:  *
91:  * Defined here (alongside other installation constants like
92:  * {@link KNOWN_CURL_DIRS}) so that both `upgrade.ts` and
93:  * `db/install-info.ts` can import it without creating a circular
94:  * dependency.
95:  */
96: export type InstallationMethod =
97:   | "curl"
98:   | "brew"
99:   | "npm"
100:   | "pnpm"
101:   | "bun"
102:   | "yarn"
103:   | "unknown";
104: 
105: /** A repository pair that hosts CLI stable releases and nightly OCI images. */
106: export type UpgradeSource = {
107:   /** GitHub `owner/repository` containing CLI release assets. */
108:   readonly githubRepo: string;
109:   /** GHCR `owner/package` containing CLI nightly images and delta patches. */
110:   readonly ghcrRepo: string;
111:   /** Prefix attached to CLI release tags in this repository. ...
gateway · 2026-09-09 13:14:11
result
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/close-dispatcher.test.ts:
  Line 2: import { closeGlobalDispatcher } from "../../src/lib/close-dispatcher.js";

  Line 4: const GLOBAL_DISPATCHER = Symbol.for("undici.globalDispatcher.1");

  Line 16: describe("closeGlobalDispatcher", () => {

  Line 17:   test("destroys the global dispatcher when one is registered", async () => {

  Line 26:     await closeGlobalDispatcher();

  Line 31:   test("resolves without throwing when no dispatcher is registered", async () => {

  Line 34:     await expect(closeGlobalDispatcher()).resolves.toBeUndefined();

  Line 37:   test("resolves when the dispatcher has no destroy method", async () => {

  Line 40:     await expect(closeGlobalDispatcher()).resolves.toBeUndefined();

  Line 48:     await ...
gateway · 2026-09-09 13:14:40
result
Found 7 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
  Line 1853: describe("downloadBinaryToTemp offline errors", () => {

  Line 1887:       await downloadBinaryToTemp("0.26.1", undefined, "explicit");

  Line 1901:       await downloadBinaryToTemp("0.26.1", undefined, "network-fallback");

  Line 1918: describe("downloadBinaryToTemp verifies download integrity (CLI-1D3)", () => {

  Line 1967:       await downloadBinaryToTemp("0.26.1");

  Line 1988:     await expect(downloadBinaryToTemp("0.26.1")).rejects.toThrow(UpgradeError);

  Line 2041:     const result = await downloadBinaryToTemp("0.26.1");
gateway · 2026-09-09 13:14:52
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts</path>
<type>file</type>
<content>
1820:           JSON.stringify({
1821:             schemaVersion: 2,
1822:             layers: [
1823:               {
1824:                 digest: "sha256:blobdigest",
1825:                 mediaType: "application/octet-stream",
1826:                 size: gzipped.byteLength,
1827:                 annotations: { "org.opencontainers.image.title": title },
1828:               },
1829:             ],
1830:             annotations: { version: "0.0.0-dev.1740000000" },
1831:           }),
1832:           { status: 200 }
1833:         );
1834:       }
1835:       if (urlStr.includes("/blobs/")) {
1836:         // Return gzipped blob directly (no redirect needed for test)
1837:         return new Response(gzipped, { status: 200 });
1838:       }
1839:       return new Response("Not Found", { status: 404 ...
gateway · 2026-09-09 13:15:17
<!-- lore-recall:2b9514ff-949d-468f-bb12-4a6d71a8a8b6 --><!-- lore-recall:37c7ba38-d215-4466-8283-782d099c398a --><!-- lore-recall:6b98b4c5-43f9-4659-a7ac-1c0a923ef8d2 -->
gpt-5.6-sol · 2026-09-09 13:15:17 · ~91 tokens
result
Found 3 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:
  Line 28:   type UpgradeSource,

  Line 29: } from "../../lib/binary.js";

  Line 62: } from "../../lib/upgrade.js";
gateway · 2026-09-09 13:15:46
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
1: /**
2:  * sentry cli upgrade
3:  *
4:  * Self-update the Sentry CLI to the latest or a specific version.
5:  * After upgrading, spawns the NEW binary with `cli setup` to update
6:  * completions, agent skills, and record installation metadata.
7:  *
8:  * Supports two release channels:
9:  * - stable (default): tracks the latest GitHub release
10:  * - nightly: tracks the rolling nightly prerelease built from main
11:  *
12:  * The channel can be set via --channel or by passing "nightly"/"stable"
13:  * as the version argument. The choice is persisted in the local database
14:  * so that subsequent bare `sentry cli upgrade` calls use the same channel. ...
gateway · 2026-09-09 13:17:53
result
No files found
gateway · 2026-09-09 13:20:18
result
Found 47 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts:
  Line 242:       await prefetchNightlyPatches(latestVersion, signal, source);

  Line 244:       await prefetchStablePatches(latestVersion, signal, source);


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
  Line 1149:   return await attemptDeltaUpgrade(


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts:
  Line 279: export function resolveStableChain(

  Line 292: export async function resolveNightlyChain(opts: {

  Line 503: export function resolveStableDelta(

  Line 522: export function resolveNightlyDelta(

  Line 541: export function attemptDeltaUpgrade(

  Line 634: export function prefetchNightlyPatches(

  Line 642: export function ...
gateway · 2026-09-09 13:23:31
result
Found 12 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts:
  Line 46: const LEGACY_UPGRADE_SOURCE = UPGRADE_SOURCES[1];

  Line 47: if (!LEGACY_UPGRADE_SOURCE) {

  Line 855:     await fetchRecentReleases(undefined, LEGACY_UPGRADE_SOURCE);

  Line 988:       resolveStableChain("0.13.0", "0.14.0", undefined, LEGACY_UPGRADE_SOURCE)

  Line 1236:         source: LEGACY_UPGRADE_SOURCE,

  Line 1922: describe("selected source affinity", () => {

  Line 1941:         LEGACY_UPGRADE_SOURCE

  Line 1966:         LEGACY_UPGRADE_SOURCE

  Line 1975:   test("prefetchStablePatches keeps requests on the legacy source", async () => {

  Line 1986:       LEGACY_UPGRADE_SOURCE

  Line 1994:   test("prefetchNightlyPatches keeps requests on the legacy source", async () => {

  Line 2006:       LEGACY_UPGRADE_SOURCE
gateway · 2026-09-09 13:27:53
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/version-check.test.ts</path>
<type>file</type>
<content>
400: });
401: 
402: describe("abortPendingVersionCheck", () => {
403:   test("does not throw when no pending check", () => {
404:     // Should be safe to call even when nothing is pending
405:     expect(() => abortPendingVersionCheck()).not.toThrow();
406:   });
407: 
408:   test("does not throw when called multiple times", () => {
409:     // Should be safe to call multiple times
410:     expect(() => {
411:       abortPendingVersionCheck();
412:       abortPendingVersionCheck();
413:       abortPendingVersionCheck();
414:     }).not.toThrow();
415:   });
416: });
417: 
418: describe("maybeCheckForUpdateInBackground", () => {
419:   useTestConfigDir("test-version-bg-");
420:   let savedNoUpdateCheck: string | undefined;
421:   let originalFetch: typeof globalThis.fetch;
422: 
423:   ...
gateway · 2026-09-09 13:30:22
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts</path>
<type>file</type>
<content>
1: /** Delta upgrade discovery and application backed by binpatch. */
2: 
3: import { join } from "node:path";
4: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
5: import * as Sentry from "@sentry/node-core/light";
6: import {
7:   applyPatchChainInMemory,
8:   extractStableChain as binpatchExtractStableChain,
9:   filterAndSortChainTags as binpatchFilterAndSortChainTags,
10:   validateChainStep as binpatchValidateChainStep,
11:   type DeltaTelemetry,
12:   type DeltaUnavailableReason,
13:   type ExtractStableChainOpts,
14:   type GitHubRelease,
15:   getPatchFromVersion,
16:   getPatchTargetSha256,
17:   ghcrSource,
18:   githubReleaseSource,
19:   type InstrumentHook,
20:   MAX_NIGHTLY_CHAIN_DEPTH,
21:   makeCache,
22:   OciClient,
23:   type OciManifest,
24: ...
gateway · 2026-09-09 13:32:27
result
/**
 * GitHub Release-asset patch source (the "stable" channel).
 *
 * Resolves a patch chain from GitHub Release assets. Each release for the
 * target platform publishes three assets:
 * - `<binaryName>`        — the binary (its digest → expected SHA-256)
 * - `<binaryName>.gz`     — gzipped binary (its size → the ratio gate)
 * - `<binaryName>.patch`  — the delta patch from the previous release
 *
 * The chain is the releases between current and target, oldest-first, capped
 * at {@link MAX_STABLE_CHAIN_DEPTH} and by {@link SIZE_THRESHOLD_RATIO}.
 *
 * All product specifics (owner/repo, binary name, user-agent, fetch) are
 * injected. Generalized from Lore's stable-channel resolver.
 */

import {
  type InstrumentHook,
  MAX_STABLE_CHAIN_DEPTH,
  type PatchChain,
  type PatchLink,
  SIZE_THRESHOLD_RATIO,
} from "../contract";
import type { SourceStrategy } from "../discover";

const SHA256_DIGEST_PATTERN = /^sha256:([0-9a-f]+)$/i;

export type GitHubAsset = {
  name: string;
  ...
gateway · 2026-09-09 13:33:17

I’m tracing the remaining source-affinity path and the Toolkit tag mismatch before returning the read-only implementation report.

gpt-5.6-sol · 2026-09-09 13:33:17 · ~22 tokens
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts</path>
<type>file</type>
<content>
210:       return true;
211:     }
212:   }
213:   return false;
214: }
215: 
216: /**
217:  * Abort any pending version check to allow process exit.
218:  * Call this when main CLI work is complete.
219:  */
220: export function abortPendingVersionCheck(): void {
221:   pendingAbortController?.abort();
222:   pendingAbortController = null;
223: }
224: 
225: /**
226:  * Pre-fetch delta patches for a newly discovered version.
227:  *
228:  * Best-effort: errors are silently caught so the version check still succeeds.
229:  * After pre-fetching, opportunistically cleans up stale cached patches. ...
gateway · 2026-09-09 13:33:25
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
380:  *
381:  * Priority:
382:  * 1. Homebrew — cheap realpath check, overrides stale stored info
383:  * 2. Stored install info in DB (fast path)
384:  * 3. Legacy detection: curl paths → subprocess calls → node_modules path
385:  * 4. Auto-save detected method for future runs
386:  *
387:  * @returns Detected installation method, or "unknown" if unable to determine
388:  */
389: export async function detectInstallationMethod(): Promise<InstallationMethod> {
390:   // Always check for Homebrew first — the stored install info may be stale
391:   // (e.g. user previously had a curl install recorded, then switched to
392:   // Homebrew). The realpath check is cheap and authoritative. ...
gateway · 2026-09-09 13:33:37
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
580: 
581: /**
582:  * Fetch the latest available version based on installation method and channel.
583:  *
584:  * - nightly channel: fetches version from GHCR manifest annotation
585:  * - curl/brew on stable: checks GitHub /releases/latest
586:  * - package managers on stable: checks npm registry
587:  *
588:  * @param method - How the CLI was installed
589:  * @param channel - Release channel ("stable" or "nightly"), defaults to "stable"
590:  * @returns Latest version string (without 'v' prefix)
591:  * @throws {UpgradeError} When version fetch fails
592:  */
593: export function fetchLatestVersion(
594:   method: InstallationMethod,
595:   channel: ReleaseChannel = "stable"
596: ): Promise<string> {
597:   if (channel === "nightly") {
598:     return fetchLatestNightlyVersion();
599:   }
600:   return ...
gateway · 2026-09-09 13:34:05
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
1010:     const delay = VERIFY_BASE_DELAY_MS * 2 ** (attempt - 1);
1011:     log.debug(
1012:       `Downloaded binary not yet visible at ${path}, retrying in ${delay}ms (attempt ${attempt}/${VERIFY_MAX_ATTEMPTS})`
1013:     );
1014:     await setTimeout(delay);
1015:   }
1016:   throw new UpgradeError(
1017:     "execution_failed",
1018:     `Downloaded binary is missing or empty at ${path}. ` +
1019:       "This is usually transient — rerun `sentry cli upgrade` to retry."
1020:   );
1021: }
1022: 
1023: /**
1024:  * Download the new binary to a temporary path and return its location.
1025:  * Used by the upgrade command to download before spawning setup --install. ...
gateway · 2026-09-09 13:34:20
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
1245:       shell: process.platform === "win32",
1246:     });
1247: 
1248:     proc.on("close", (code) => {
1249:       if (code === 0) {
1250:         resolve();
1251:       } else {
1252:         reject(
1253:           new UpgradeError(
1254:             "execution_failed",
1255:             `${pm} install failed with exit code ${code}`
1256:           )
1257:         );
1258:       }
1259:     });
1260: 
1261:     proc.on("error", (err) => {
1262:       reject(
1263:         new UpgradeError("execution_failed", `${pm} failed: ${err.message}`)
1264:       );
1265:     });
1266:   });
1267: }
1268: 
1269: /**
1270:  * Execute the upgrade using the appropriate method. ...
gateway · 2026-09-09 13:34:36
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
250:   offline: boolean
251: ): void {
252:   if (method === "unknown") {
253:     throw new UpgradeError("unknown_method");
254:   }
255:   // Homebrew manages versioning through the formula — pinning a specific
256:   // stable version is not supported via this command.
257:   if (method === "brew" && versionArg && channel === "stable") {
258:     throw new UpgradeError(
259:       "unsupported_operation",
260:       "Homebrew does not support installing a specific version. Run 'brew upgrade getsentry/tools/sentry' to upgrade to the latest formula version."
261:     );
262:   }
263:   // Offline mode is only supported for curl-installed binaries — package
264:   // managers always need network to fetch and install packages.
265:   if (offline && method !== "curl") {
266:     throw new ...
gateway · 2026-09-09 13:34:46
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
340:     return {
341:       kind: "done",
342:       result: buildCheckResult({ target, versionArg, method, channel, flags }),
343:       source: latestResolution?.source,
344:     };
345:   }
346: 
347:   // Skip if already on target — unless forced or switching channels
348:   if (CLI_VERSION === target && !flags.force && !channelChanged) {
349:     return {
350:       kind: "done",
351:       result: {
352:         action: "up-to-date",
353:         currentVersion: CLI_VERSION,
354:         targetVersion: target,
355:         channel,
356:         method,
357:         forced: false,
358:       },
359:     };
360:   }
361: 
362:   // Validate that a specific pinned version actually exists. ...
gateway · 2026-09-09 13:35:01
result
Found 9 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:
  Line 218:       source: resolved.source,

  Line 309:   return resolved.source;

  Line 645: async function executeStandardUpgrade(opts: {

  Line 680:       executeUpgrade(method, target, downloadTag, offline, setMessage, source)

  Line 748: async function migrateToStandaloneForNightly(opts: {

  Line 766:       executeUpgrade("curl", target, downloadTag, undefined, setMessage, source)

  Line 1005:           source: resolved.source,

  Line 1058:       warnings = await migrateToStandaloneForNightly({

  Line 1067:       await executeStandardUpgrade({
gateway · 2026-09-09 13:35:31
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
180:       target: string;
181:       offline: OfflineMode;
182:       source?: UpgradeSource;
183:     }
184:   | { kind: "done"; result: UpgradeResult }
185: > {
186:   const { resolveOpts, versionArg, offline, method, persistChannelFn } = opts;
187: 
188:   if (offline) {
189:     // Channel switching with --offline is not supported: the cached version
190:     // belongs to the old channel and would install the wrong binary type.
191:     if (resolveOpts.channelChanged && !versionArg) {
192:       throw new UpgradeError(
193:         "unsupported_operation",
194:         "Cannot switch channels in offline mode — the cached version belongs to the current channel. " +
195:           "Run 'sentry cli upgrade' with network access to switch channels."
196:       );
197:     }
198:     // Read the ...
gateway · 2026-09-09 13:36:15
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
630:   const { SENTRY_INSTALL_DIR: _pinned, ...envWithoutPin } = process.env;
631:   const xdgInstallDir = determineInstallDir(homedir(), envWithoutPin);
632:   if (
633:     !samePath(xdgInstallDir, legacyBinDir) &&
634:     isInPath(xdgInstallDir, pathEnv)
635:   ) {
636:     return xdgInstallDir;
637:   }
638:   return currentInstallDir;
639: }
640: 
641: /**
642:  * Execute the standard upgrade path: download via curl or package manager,
643:  * then run setup on the new binary.
644:  */
645: async function executeStandardUpgrade(opts: {
646:   method: InstallationMethod;
647:   channel: ReleaseChannel;
648:   versionArg: string | undefined;
649:   target: string;
650:   execPath: string;
651:   entryPath?: string;
652:   pathEnv?: string;
653:   offline?: OfflineMode;
654:   json?: boolean;
655:  ...
gateway · 2026-09-09 13:36:36
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
960:         kind: "boolean",
961:         brief: "Skip agent skill installation for AI coding assistants",
962:         default: false,
963:       },
964:       method: {
965:         kind: "parsed",
966:         parse: parseInstallationMethod,
967:         brief: "Installation method to use (curl, brew, npm, pnpm, bun, yarn)",
968:         optional: true,
969:         placeholder: "method",
970:       },
971:     },
972:   },
973:   async *func(this: SentryContext, flags: UpgradeFlags, version?: string) {
974:     const { channel, versionArg, channelChanged, method } =
975:       await resolveContext(version, flags);
976: 
977:     log.debug(`Installation method: ${method}`);
978:     log.debug(`Current version: ${CLI_VERSION}`);
979: 
980:     const resolved = await withProgress(
981:       { ...
gateway · 2026-09-09 13:37:50
result
 M .github/workflows/ci.yml
 M packages/cli/install
 M packages/cli/package.json
 M packages/cli/src/commands/cli/upgrade.ts
 M packages/cli/src/lib/binary.ts
 M packages/cli/src/lib/delta-upgrade.ts
 M packages/cli/src/lib/ghcr.ts
 M packages/cli/src/lib/release-notes.ts
 M packages/cli/src/lib/upgrade.ts
 M packages/cli/src/lib/version-check.ts
 M packages/cli/test/commands/cli/upgrade.test.ts
 M packages/cli/test/lib/binary.test.ts
 M packages/cli/test/lib/delta-upgrade.test.ts
 M packages/cli/test/lib/ghcr.test.ts
 M packages/cli/test/lib/install-script.test.ts
 M packages/cli/test/lib/release-notes.test.ts
 M packages/cli/test/lib/upgrade.test.ts
 M packages/cli/test/lib/version-check.test.ts
 .github/workflows/ci.yml                       |   1 +
 packages/cli/install                           | 192 +++++++++++---
 packages/cli/package.json                      |   3 +-
 packages/cli/src/commands/cli/upgrade.ts       | 114 ++++++---
 packages/cli/src/lib/binary.ts                ...
gateway · 2026-09-09 13:40:50
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
800:     });
801:   });
802: });
803: 
804: // ===================================================================
805: // Async functions (fetch-mocked)
806: // ===================================================================
807: 
808: /** Helper to mock globalThis.fetch */
809: function mockFetch(
810:   fn: (url: string | URL | Request, init?: RequestInit) => Promise<Response>
811: ): void {
812:   globalThis.fetch = fn as typeof globalThis.fetch;
813: }
814: 
815: /** Store original fetch for restoration */
816: let originalFetch: typeof globalThis.fetch;
817: 
818: beforeEach(() => {
819:   originalFetch = globalThis.fetch;
820: });
821: 
822: afterEach(() => {
823:   globalThis.fetch = originalFetch;
824: });
825: 
826: // fetchRecentReleases
827: 
828: describe("fetchRecentReleases", () ...
gateway · 2026-09-09 13:43:04
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
1900:       throw new Error("fetch should not be called");
1901:     });
1902: 
1903:     await prefetchStablePatches("0.14.0");
1904:   });
1905: });
1906: 
1907: async function importDeltaUpgradeWithVersion(version: string) {
1908:   vi.resetModules();
1909:   vi.doMock("../../src/lib/constants.js", async (importOriginal) => {
1910:     const actual =
1911:       await importOriginal<typeof import("../../src/lib/constants.js")>();
1912:     return { ...actual, CLI_VERSION: version };
1913:   });
1914:   return import("../../src/lib/delta-upgrade.js");
1915: }
1916: 
1917: function restoreDeltaUpgradeModule(): void {
1918:   vi.doUnmock("../../src/lib/constants.js");
1919:   vi.resetModules();
1920: }
1921: 
1922: describe("selected source affinity", () => {
1923:   ...
gateway · 2026-09-09 13:44:10
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.mocked.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Integration tests for delta upgrade orchestration with a non-dev CLI_VERSION.
3:  *
4:  * These tests use `vi.mock()` to override `CLI_VERSION` from constants.js
5:  * so that `canAttemptDelta()` passes its dev-build guard (the real `CLI_VERSION`
6:  * is "0.0.0-dev" in test mode, which short-circuits the orchestrator).
7:  *
8:  * Kept as a sibling file to `delta-upgrade.test.ts` because its
9:  * `vi.mock()` would invert the assumptions of the dev-mode null-return
10:  * tests in that file. Under `bun test --isolate` each file gets a fresh
11:  * module graph, so the mocks here don't leak. ...
gateway · 2026-09-09 13:45:28
result
Found 47 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts:
  Line 970:     const chain = await resolveStableChain("0.13.0", "0.14.0");

  Line 988:       resolveStableChain("0.13.0", "0.14.0", undefined, LEGACY_UPGRADE_SOURCE)

  Line 1039:     const chain = await resolveStableChain("0.13.0", "0.15.0");

  Line 1057:     const chain = await resolveStableChain("0.12.0", "0.14.0");

  Line 1064:     const chain = await resolveStableChain("0.12.0", "0.13.0");

  Line 1089:     const chain = await resolveStableChain("0.13.0", "0.14.0");

  Line 1112:     const chain = await resolveStableChain("0.1.0", "0.15.0");

  Line 1208:     const chain = await resolveNightlyChain({

  Line 1231:       resolveNightlyChain({

  Line 1246:     const chain = await resolveNightlyChain({

  Line 1265:     const chain = await resolveNightlyChain({

  Line 1320:     const chain = await ...
gateway · 2026-09-09 13:47:35
result
import { afterEach, describe, expect, it, vi } from "vitest";
import {
  type InstrumentHook,
  extractSha256,
  extractStableChain,
  filterAndSortChainTags,
  getPatchFromVersion,
  getPatchTargetSha256,
  ghcrSource,
  type GitHubRelease,
  githubReleaseSource,
  getStableTargetSha256,
  OciClient,
  type OciManifest,
  validateChainStep,
} from "../src";

// Build a JSON Response for mocked fetch calls.
function json(body: unknown): Response {
  return new Response(JSON.stringify(body), {
    status: 200,
    headers: { "content-type": "application/json" },
  });
}

// A semver-ish comparator matching the gateway's compareVersions contract
// (returns -1 | 0 | 1) for the nightly tag-ordering tests.
function cmp(a: string, b: string): -1 | 0 | 1 {
  const pa = a.split(".").map(Number);
  const pb = b.split(".").map(Number);
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
    const x = pa[i] ?? 0;
    const y = pb[i] ?? ...
gateway · 2026-09-09 13:50:22
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/patch-cache.ts</path>
<type>file</type>
<content>
1: import { join } from "node:path";
2: import { makeCache, type PatchCache, type PatchChain } from "binpatch";
3: import { getConfigDir } from "./db/index.js";
4: 
5: export type { ChainMeta, PatchStepMeta } from "binpatch";
6: // biome-ignore lint/performance/noBarrelFile: preserve the existing cache API
7: export { chainFileName, patchFileName } from "binpatch";
8: 
9: function cache(): PatchCache {
10:   return makeCache(join(getConfigDir(), "patch-cache"));
11: }
12: 
13: export function savePatchesToCache(
14:   chain: Pick<PatchChain, "patches" | "expectedSha256">,
15:   steps: { fromVersion: string; toVersion: string }[]
16: ): Promise<void> {
17:   return cache().save(chain, steps);
18: }
19: 
20: export async function loadCachedChain(
21:   currentVersion: string,
22:   targetVersion: string
23: ...
gateway · 2026-09-09 13:51:30
result
/**
 * Chain discovery + resolve-and-apply orchestration.
 *
 * A {@link SourceStrategy} knows how to resolve a {@link PatchChain} from some
 * backing store (an OCI registry, GitHub Release assets, ...). This module ties
 * a strategy together with the offline cache, the apply core, integrity
 * verification, and progress events — with every product-specific concern
 * (version, telemetry, logging, cache location) injected.
 */

import { applyPatchChainInMemory, parsePatchHeader } from "./bspatch";
import type { PatchCache } from "./patch-cache";
import type { DeltaResult, PatchChain } from "./contract";
import { type ProgressHandler, safeProgress } from "./events";

/**
 * A source of patch chains. Given the current and target versions, resolve the
 * ordered chain of patches (oldest hop first) plus the expected final SHA-256,
 * or `null` when no usable chain exists (caller falls back to a full download). ...
gateway · 2026-09-09 13:56:36
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
80: /**
81:  * Absolute legacy install directories for the given home. See
82:  * {@link LEGACY_INSTALL_SUBDIRS} for why this is scoped to pre-XDG locations.
83:  */
84: export function getLegacyInstallDirs(homeDir: string): string[] {
85:   return LEGACY_INSTALL_SUBDIRS.map((dir) => join(homeDir, dir));
86: }
87: 
88: /**
89:  * How the CLI was installed. Determines the upgrade strategy.
90:  *
91:  * Defined here (alongside other installation constants like
92:  * {@link KNOWN_CURL_DIRS}) so that both `upgrade.ts` and
93:  * `db/install-info.ts` can import it without creating a circular
94:  * dependency. ...
gateway · 2026-09-09 14:01:24
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
390:   // Always check for Homebrew first — the stored install info may be stale
391:   // (e.g. user previously had a curl install recorded, then switched to
392:   // Homebrew). The realpath check is cheap and authoritative.
393:   if (isHomebrewInstall()) {
394:     return "brew";
395:   }
396: 
397:   // Check stored info (fast path for non-Homebrew installs)
398:   const stored = getInstallInfo();
399:   if (stored?.method) {
400:     return stored.method;
401:   }
402: 
403:   // Legacy detection for existing installs (pre-setup command)
404:   const legacyMethod = await detectLegacyInstallationMethod();
405: 
406:   // Auto-save detected method for future runs (best-effort —
407:   // a read-only or broken DB shouldn't block detection)
408:   if (legacyMethod !== "unknown") {
409:     try {
410:       ...
gateway · 2026-09-09 14:02:48
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
615: /** Resolve and validate a pinned standalone version against ordered sources. */
616: export async function resolveExistingUpgradeVersion(
617:   version: string
618: ): Promise<ResolvedUpgradeVersion | null> {
619:   try {
620:     if (isNightlyVersion(version)) {
621:       const resolved = await resolveNightlyManifest(
622:         `nightly-${version}`,
623:         undefined,
624:         UPGRADE_SOURCES
625:       );
626:       return { version, source: resolved.source };
627:     }
628:     const selected = await resolveUpgradeSource({
629:       getProbeUrl: (source) => getGitHubReleaseByTagUrl(version, source),
630:     });
631:     return { version, source: selected.source };
632:   } catch (error) {
633:     if (isUpgradeSourceNotFound(error)) {
634:       return null;
635:     }
636:     throw ...
gateway · 2026-09-09 14:03:51
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
1010:     const delay = VERIFY_BASE_DELAY_MS * 2 ** (attempt - 1);
1011:     log.debug(
1012:       `Downloaded binary not yet visible at ${path}, retrying in ${delay}ms (attempt ${attempt}/${VERIFY_MAX_ATTEMPTS})`
1013:     );
1014:     await setTimeout(delay);
1015:   }
1016:   throw new UpgradeError(
1017:     "execution_failed",
1018:     `Downloaded binary is missing or empty at ${path}. ` +
1019:       "This is usually transient — rerun `sentry cli upgrade` to retry."
1020:   );
1021: }
1022: 
1023: /**
1024:  * Download the new binary to a temporary path and return its location.
1025:  * Used by the upgrade command to download before spawning setup --install. ...
gateway · 2026-09-09 14:04:42
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
850: function getNightlyGzFilename(): string {
851:   return `${getPlatformBinaryName()}.gz`;
852: }
853: 
854: /**
855:  * Download a nightly binary from GHCR and decompress it to `destPath`.
856:  *
857:  * Fetches an anonymous token, retrieves the OCI manifest, finds the layer
858:  * matching this platform's `.gz` filename, then downloads and decompresses
859:  * the blob in-stream.
860:  *
861:  * When `version` is provided, fetches the pinned versioned tag
862:  * (`nightly-{version}`). Otherwise fetches the rolling `:nightly` tag. ...
gateway · 2026-09-09 14:05:39
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
190:     // belongs to the old channel and would install the wrong binary type.
191:     if (resolveOpts.channelChanged && !versionArg) {
192:       throw new UpgradeError(
193:         "unsupported_operation",
194:         "Cannot switch channels in offline mode — the cached version belongs to the current channel. " +
195:           "Run 'sentry cli upgrade' with network access to switch channels."
196:       );
197:     }
198:     // Read the cached version BEFORE persisting the channel — setReleaseChannel
199:     // clears the version cache on channel changes.
200:     const target = resolveOfflineTarget(versionArg);
201:     persistChannelFn();
202:     log.info(`Offline mode: using cached target ${target}`);
203:     return { kind: "target", target, offline: "explicit" };
204:   }
205: 
206:   ...
gateway · 2026-09-09 14:06:01
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts</path>
<type>file</type>
<content>
819: /**
820:  * Resolve the channel, version arg, method, and channel-changed flag from
821:  * the positional version argument and flags. Extracted to keep `func()`
822:  * complexity under the biome limit.
823:  */
824: async function resolveContext(
825:   version: string | undefined,
826:   flags: UpgradeFlags
827: ): Promise<{
828:   channel: ReleaseChannel;
829:   versionArg: string | undefined;
830:   channelChanged: boolean;
831:   method: InstallationMethod;
832: }> {
833:   const { channel, versionArg } = resolveChannelAndVersion(version);
834:   const currentChannel = getReleaseChannel();
835:   const channelChanged = channel !== currentChannel;
836: 
837:   const method = flags.method ?? (await detectInstallationMethod());
838:   validateMethod(method, versionArg, channel, ...
gateway · 2026-09-09 14:07:59
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade</path>
<type>directory</type>
<entries>
.craft.yml
.git
.github/
.gitignore
.lore.md
.nojekyll
.npmrc
AGENTS.md
apps/
CHANGELOG.md
codemods/
docs/
LICENSE.md
node_modules/
package.json
packages/
pnpm-lock.yaml
pnpm-workspace.yaml
README.md

(19 entries)
</entries>
gateway · 2026-09-09 14:08:13
result
File not found: /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/.cursor/rules/ultracite.mdc
gateway · 2026-09-09 14:08:41
result
No files found
gateway · 2026-09-09 14:09:06
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/AGENTS.md</path>
<type>file</type>
<content>
1: # Jared (Outpost agent)
2: 
3: Autonomous GitHub coding agent. Work in `/workspace/repo`.
4: 
5: ## Model tiers
6: 
7: The primary model is chosen per event (see `src/agents/models.ts`): heavy for
8: code-producing situations, cheaper for lightweight ones.
9: 
10: | Role | Subagent | Model |
11: | --- | --- | --- |
12: | Triage / plan / review (heavy) | (primary Jared) | Claude Opus 4.8 |
13: | Triage / plan / review (light) | (primary Jared) | xAI Grok 4.3 |
14: | Explore | `explore` | OpenAI gpt-5-mini |
15: | Implement | `implement` | Moonshot kimi-k2.7-code |
16: | Ship (commit/push/PR) | `ship` | xAI Grok (`grok-build-0.1`) |
17: 
18: Pipeline: triage → explore → plan → implement → review → ship.
19: (`worker` is a deprecated alias of `implement`.)
20: 
21: Operators also talk to Jared directly from the Outpost dashboard. ...
gateway · 2026-09-09 14:09:24
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/AGENTS.md</path>
<type>file</type>
<content>
1: # AGENTS.md
2: 
3: Guidelines for AI agents working in this codebase.
4: 
5: ## Project Overview
6: 
7: **Sentry CLI** is a command-line interface for [Sentry](https://sentry.io), built with Node.js, [pnpm](https://pnpm.io), and [Stricli](https://bloomberg.github.io/stricli/). It lives in `packages/cli` of a pnpm workspace; the docs site lives in `apps/cli-docs`. ...
gateway · 2026-09-09 14:10:01
result
StatusCode: non 2xx status code (404 GET https://raw.githubusercontent.com/BYK/binpatch/9ba6bbb8227fcbd2521852d2311c82afac5e9573/src/github-release.ts)
gateway · 2026-09-09 14:10:26
result
{
  "sha": "9ba6bbb8227fcbd2521852d2311c82afac5e9573",
  "url": "https://api.github.com/repos/BYK/binpatch/git/trees/9ba6bbb8227fcbd2521852d2311c82afac5e9573",
  "tree": [
    {
      "path": ".craft.yml",
      "mode": "100644",
      "type": "blob",
      "sha": "36f34fdd754de842419fe5a5cb2844a8c98f80df",
      "size": 1143,
      "url": "https://api.github.com/repos/BYK/binpatch/git/blobs/36f34fdd754de842419fe5a5cb2844a8c98f80df"
    },
    {
      "path": ".github",
      "mode": "040000",
      "type": "tree",
      "sha": "dc6a71d7d4d393c0e072cb45ac745fc2a61f60ef",
      "url": "https://api.github.com/repos/BYK/binpatch/git/trees/dc6a71d7d4d393c0e072cb45ac745fc2a61f60ef"
    },
    {
      "path": ".github/workflows",
      "mode": "040000",
      "type": "tree",
      "sha": "da820a4798f068f6531c69b3544f97601baa4cfa",
      "url": "https://api.github.com/repos/BYK/binpatch/git/trees/da820a4798f068f6531c69b3544f97601baa4cfa"
    },
    {
      "path": ...
gateway · 2026-09-09 14:10:45
result
/**
 * GitHub Release-asset patch source (the "stable" channel).
 *
 * Resolves a patch chain from GitHub Release assets. Each release for the
 * target platform publishes three assets:
 * - `<binaryName>`        — the binary (its digest → expected SHA-256)
 * - `<binaryName>.gz`     — gzipped binary (its size → the ratio gate)
 * - `<binaryName>.patch`  — the delta patch from the previous release
 *
 * The chain is the releases between current and target, oldest-first, capped
 * at {@link MAX_STABLE_CHAIN_DEPTH} and by {@link SIZE_THRESHOLD_RATIO}.
 *
 * All product specifics (owner/repo, binary name, user-agent, fetch) are
 * injected. Generalized from Lore's stable-channel resolver.
 */

import {
  type InstrumentHook,
  MAX_STABLE_CHAIN_DEPTH,
  type PatchChain,
  type PatchLink,
  SIZE_THRESHOLD_RATIO,
} from "../contract";
import type { SourceStrategy } from "../discover";

const SHA256_DIGEST_PATTERN = /^sha256:([0-9a-f]+)$/i;

export type GitHubAsset = {
  name: string;
  ...
gateway · 2026-09-09 14:11:53

I have enough evidence to close the review. I’m checking the current patch once more so the report reflects the latest source rather than an earlier snapshot.

gpt-5.6-sol · 2026-09-09 14:11:53 · ~30 tokens
result
(no output)
gateway · 2026-09-09 14:12:11
result
## feat/toolkit-bridge-upgrade...origin/feat/toolkit-bridge-upgrade
4094ae9a7 (HEAD -> feat/toolkit-bridge-upgrade, origin/feat/toolkit-bridge-upgrade) feat(cli): add toolkit upgrade bridge
bd065083c (origin/main, origin/HEAD) feat(local): Add Vercel Analytics (#1563)
4ca8818d1 feat(local): Add browser viewer for local telemetry (#1560)
0e661a5f5 fix(org): log region URL parse failures in org list (#1539)
9d0901b10 feat(local): Add agent debugging stream (#1538)
 .github/workflows/ci.yml                       |   1 +
 package.json                                   |   3 +-
 packages/cli/install                           | 192 +++++++++++---
 packages/cli/package.json                      |   3 +-
 packages/cli/src/commands/cli/upgrade.ts       | 114 ++++++---
 packages/cli/src/lib/binary.ts                 | 146 ++++++++++-
 packages/cli/src/lib/delta-upgrade.ts          |  81 +++---
 packages/cli/src/lib/ghcr.ts                   |  48 ++--
 packages/cli/src/lib/release-notes.ts      ...
gateway · 2026-09-09 14:12:45
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts</path>
<type>file</type>
<content>
1: /** Delta upgrade discovery and application backed by binpatch. */
2: 
3: import { join } from "node:path";
4: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
5: import * as Sentry from "@sentry/node-core/light";
6: import {
7:   applyPatchChainInMemory,
8:   extractStableChain as binpatchExtractStableChain,
9:   filterAndSortChainTags as binpatchFilterAndSortChainTags,
10:   validateChainStep as binpatchValidateChainStep,
11:   type DeltaTelemetry,
12:   type DeltaUnavailableReason,
13:   type ExtractStableChainOpts,
14:   type GitHubRelease,
15:   getPatchFromVersion,
16:   getPatchTargetSha256,
17:   ghcrSource,
18:   githubReleaseSource,
19:   type InstrumentHook,
20:   MAX_NIGHTLY_CHAIN_DEPTH,
21:   makeCache,
22:   OciClient,
23:   type OciManifest,
24: ...
gateway · 2026-09-09 14:13:41
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/custom-ca.ts</path>
<type>file</type>
<content>
1: /**
2:  * Custom CA certificate loading for corporate TLS proxies.
3:  *
4:  * Reads CA bundles from (in priority order):
5:  * 1. `sentry cli defaults ca-cert` (stored path in SQLite)
6:  * 2. `NODE_EXTRA_CA_CERTS` env var
7:  *
8:  * Returns a `tls` options object for Bun's `fetch()`. On the Node.js npm
9:  * distribution, Node natively honors `NODE_EXTRA_CA_CERTS` so the extra
10:  * `tls.ca` option is harmless (ignored by Node's fetch).
11:  *
12:  * Security model: When the CA source is an env var (not a stored default)
13:  * AND the target is SaaS (`*.sentry.io`), a one-time warning is logged.
14:  * `sentry cli defaults ca-cert` silences the warning — the user has
15:  * explicitly acknowledged the custom CA. See CLI-1K6 plan for the full
16:  * threat model discussion. ...
gateway · 2026-09-09 14:13:53
result
Found 1 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/custom-ca.ts:
  Line 305: export function customFetch(
gateway · 2026-09-09 14:14:04
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/custom-ca.ts</path>
<type>file</type>
<content>
285:  * Get the combined CA certificate PEM string for Node.js `http.request()`.
286:  * Returns undefined when no custom CAs are configured.
287:  *
288:  * Unlike {@link getCustomTlsOptions} (which returns Bun's `{ tls: { ca } }` shape),
289:  * this returns the raw PEM string suitable for Node's `https.RequestOptions.ca`
290:  * and the Sentry SDK's `NodeTransportOptions.caCerts`.
291:  */
292: export function getCustomCaCerts(): string | undefined {
293:   resolve();
294:   return resolved?.tls.ca;
295: }
296: 
297: /**
298:  * Drop-in replacement for `fetch()` that injects custom CA certificates
299:  * when configured. All non-authenticated fetch call sites should use this
300:  * instead of bare `fetch()`.
301:  *
302:  * Authenticated API calls go through `fetchWithTimeout()` in sentry-client.ts
303: ...
gateway · 2026-09-09 14:15:12
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
790:     ]);
791:     const result = validateChainStep(manifest, {
792:       expectedFrom: "0.0.9",
793:       patchLayerName: PATCH_LAYER_NAME,
794:       sizeLimit: 100_000,
795:     });
796:     expect(result).toEqual({
797:       ok: true,
798:       digest: `sha256:${PATCH_LAYER_NAME.replace(/\W/g, "")}`,
799:       size: 500,
800:     });
801:   });
802: });
803: 
804: // ===================================================================
805: // Async functions (fetch-mocked)
806: // ===================================================================
807: 
808: /** Helper to mock globalThis.fetch */
809: function mockFetch(
810:   fn: (url: string | URL | Request, init?: RequestInit) => Promise<Response>
811: ): void {
812:   globalThis.fetch = fn as typeof globalThis.fetch;
813: }
814: ...
gateway · 2026-09-09 14:16:28
result
/**
 * binpatch — reusable binary delta-update engine.
 *
 * Two things, joined by one wire contract (see README):
 * - **apply core** — parse + apply a TRDIFF10/bsdiff patch chain to a binary.
 * - **discovery** — resolve a patch chain from a pluggable `SourceStrategy`
 *   (OCI/GHCR tags or GitHub Release assets), then apply + verify it.
 *
 * Pure Node (`node:*` builtins only), zero product coupling — the consumer
 * injects the cache directory, the download source, version comparison,
 * progress handling, and telemetry.
 */

export {
  addDiffChunk,
  applyPatch,
  applyPatchChainInMemory,
  applyPatchToMemory,
  MAX_OUTPUT_SIZE,
  offtin,
  parsePatchHeader,
  type PatchHeader,
} from "./bspatch";

export {
  type ChainMeta,
  chainFileName,
  makeCache,
  type PatchCache,
  patchFileName,
  type PatchStepMeta,
} from "./patch-cache";

// Wire-contract constants + shared chain types. ...
gateway · 2026-09-09 14:18:11
result
No files found
gateway · 2026-09-09 14:18:26
result
Found 7 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
  Line 28:   fetchWithUpgradeError,

  Line 476:   const response = await fetchWithUpgradeError(

  Line 677:       await fetchWithUpgradeError(

  Line 709:   const response = await fetchWithUpgradeError(

  Line 919:     const gzResponse = await fetchWithUpgradeError(

  Line 933:   const response = await fetchWithUpgradeError(url, { headers }, "GitHub");


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts:
  Line 482: export async function fetchWithUpgradeError(
gateway · 2026-09-09 14:18:34
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
450: 
451:   for (const dir of candidates) {
452:     if (existsSync(dir) && pathDirs.some((p) => samePath(p, dir))) {
453:       return dir;
454:     }
455:   }
456: 
457:   // 5. XDG-aligned fallback — setup will handle adding this to PATH
458:   return join(homeDir, ".local", "bin");
459: }
460: 
461: /**
462:  * Build headers for GitHub API requests.
463:  */
464: export function getGitHubHeaders(): Record<string, string> {
465:   return {
466:     Accept: "application/vnd.github.v3+json",
467:     "User-Agent": getUserAgent(),
468:   };
469: }
470: 
471: /**
472:  * Fetch wrapper that converts network errors to UpgradeError.
473:  * Handles DNS failures, timeouts, and other connection issues. ...
gateway · 2026-09-09 14:19:26
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts</path>
<type>file</type>
<content>
560:       sections.push({ category, markdown });
561:     }
562:   }
563: 
564:   return sections;
565: }
566: 
567: // ────────────────────────────── Fetch Functions ────────────────────────────
568: 
569: /**
570:  * Max releases to fetch for changelog purposes.
571:  *
572:  * Higher than the delta-upgrade cap (12) to cover larger version jumps.
573:  * GitHub API max per_page is 100; 30 covers ~6+ months of weekly releases.
574:  */
575: const CHANGELOG_MAX_RELEASES = 30;
576: 
577: /**
578:  * Fetch recent releases from GitHub for changelog building.
579:  *
580:  * Uses a higher `per_page` than `fetchRecentReleases()` in delta-upgrade
581:  * (which is capped at 12 for patch chain resolution) to cover larger
582:  * version jumps without silent truncation. ...
gateway · 2026-09-09 14:19:39
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts</path>
<type>file</type>
<content>
1: /**
2:  * Release Notes Parser & Aggregation
3:  *
4:  * Extracts user-facing changelog entries from GitHub Release bodies (stable)
5:  * or conventional commit messages (nightly). Uses `marked.lexer()` for
6:  * AST-based section extraction and produces structured data that can be
7:  * re-serialized as filtered markdown for rendering via `renderMarkdown()`. ...
gateway · 2026-09-09 14:19:48
result
Found 7 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts:
  Line 427: function buildChangelogSummaryForSource(

  Line 435:     let tagName = release.tag_name;

  Line 436:     if (source?.tagPrefix) {

  Line 437:       if (!tagName.startsWith(source.tagPrefix)) {

  Line 440:       tagName = tagName.slice(source.tagPrefix.length);

  Line 477:   return buildChangelogSummaryForSource(releases, fromVersion, toVersion, {

  Line 637:   return buildChangelogSummaryForSource(releases, fromVersion, toVersion, {
gateway · 2026-09-09 14:20:02
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts</path>
<type>file</type>
<content>
390: function mergeSectionsByCategory(releases: GitHubRelease[]): ChangeSection[] {
391:   const sectionsByCategory = new Map<ChangeCategory, string[]>();
392: 
393:   for (const release of releases) {
394:     if (!release.body) {
395:       continue;
396:     }
397:     const sections = extractSections(release.body);
398:     for (const section of sections) {
399:       const stripped = stripAttributions(section.markdown);
400:       const existing = sectionsByCategory.get(section.category) ?? [];
401:       existing.push(stripped);
402:       sectionsByCategory.set(section.category, existing);
403:     }
404:   }
405: 
406:   // Build merged sections in display order
407:   const merged: ChangeSection[] = [];
408:   for (const category of CATEGORY_ORDER) {
409:     const markdowns = ...
gateway · 2026-09-09 14:21:11
result
Found 6 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts:
  Line 843:     const result = await fetchRecentReleases();

  Line 855:     await fetchRecentReleases(undefined, LEGACY_UPGRADE_SOURCE);

  Line 865:     const result = await fetchRecentReleases();

  Line 874:     const result = await fetchRecentReleases();


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts:
  Line 580:  * Uses a higher `per_page` than `fetchRecentReleases()` in delta-upgrade


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts:
  Line 160: export async function fetchRecentReleases(
gateway · 2026-09-09 14:21:45
result
Found 23 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
  Line 601:     await expect(versionExists("curl", "1.0.0")).resolves.toBe(true);

  Line 616:     await expect(versionExists("curl", "1.0.0")).resolves.toBe(true);

  Line 631:       versionExists("curl", "1.0.0", UPGRADE_SOURCES[0])

  Line 641:     const exists = await versionExists("curl", "1.0.0");

  Line 648:     const exists = await versionExists("curl", "99.99.99");

  Line 655:     const exists = await versionExists("npm", "1.0.0");

  Line 662:     const exists = await versionExists("npm", "99.99.99");

  Line 669:     const exists = await versionExists("pnpm", "1.0.0");

  Line 676:     const exists = await versionExists("bun", "1.0.0");

  Line 683:     const exists = await versionExists("brew", "1.0.0");

  Line 690:     const exists = await versionExists("brew", "99.99.99");

  Line 697:     const exists = await ...
gateway · 2026-09-09 14:21:56
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts</path>
<type>file</type>
<content>
580:         new Response(JSON.stringify([{ tag_name: "cli@v3.0.0" }]), {
581:           status: 200,
582:           headers: { "Content-Type": "application/json" },
583:         })
584:     );
585: 
586:     const version = await fetchLatestVersion("curl");
587:     expect(version).toBe("3.0.0");
588:   });
589: });
590: 
591: describe("versionExists", () => {
592:   test("probes prefixed Toolkit tags and retains the selected source", async () => {
593:     const requests: string[] = [];
594:     mockFetch(async (url) => {
595:       requests.push(String(url));
596:       return new Response(JSON.stringify({ tag_name: "cli@1.0.0" }), {
597:         status: 200,
598:       });
599:     });
600: 
601:     await expect(versionExists("curl", "1.0.0")).resolves.toBe(true);
602:     ...
gateway · 2026-09-09 14:25:26
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
1850:     };
1851: 
1852:     setupFullNightlyMocks({
1853:       targetVersion: "0.14.0-dev.200",
1854:       targetManifest,
1855:       patchTags: ["patch-0.14.0-dev.200"],
1856:       patchManifests: new Map(),
1857:       blobs: new Map(),
1858:     });
1859: 
1860:     const result = await resolveNightlyDelta(
1861:       "0.14.0-dev.200",
1862:       "/tmp/fake-old",
1863:       "/tmp/fake-out"
1864:     );
1865:     expect(result).toBeNull();
1866:   });
1867: });
1868: 
1869: // attemptDeltaUpgrade (top-level orchestrator)
1870: 
1871: describe("attemptDeltaUpgrade", () => {
1872:   test("returns null when canAttemptDelta is false (dev version)", async () => {
1873:     const result = await attemptDeltaUpgrade(
1874:       "0.14.0",
1875:       "/tmp/fake-old",
1876:       ...
gateway · 2026-09-09 14:26:02
result
Found 1 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
  Line 105: function extractReleaseVersions(
gateway · 2026-09-09 14:26:10
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
75: type PackageManager = "npm" | "pnpm" | "bun" | "yarn";
76: 
77: /**
78:  * How the current upgrade reached the offline code path.
79:  *
80:  * - `false` — online upgrade (network available)
81:  * - `"explicit"` — user passed `--offline` flag
82:  * - `"network-fallback"` — network failed, auto-fell back to cache
83:  */
84: export type OfflineMode = false | "explicit" | "network-fallback";
85: 
86: // Constants
87: 
88: /** The git tag used for the rolling nightly GitHub release (stable fallback only). */
89: export const NIGHTLY_TAG = "nightly";
90: 
91: /** npm registry base URL */
92: const NPM_REGISTRY_URL = "https://registry.npmjs.org/sentry";
93: 
94: /** Regex to strip 'v' prefix from version strings */
95: export const VERSION_PREFIX_REGEX = /^v/;
96: 
97: /** A resolved standalone-binary version ...
gateway · 2026-09-09 14:26:56
result
Found 15 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts:
  Line 32:   fetchLatestFromGitHubWithSource,

  Line 292:             : await fetchLatestFromGitHubWithSource(signal);


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
  Line 98: export type ResolvedUpgradeVersion = {

  Line 433: export async function fetchLatestFromGitHubWithSource(

  Line 436: ): Promise<ResolvedUpgradeVersion> {

  Line 462:     await fetchLatestFromGitHubWithSource(

  Line 512: ): Promise<ResolvedUpgradeVersion> {

  Line 609: ): Promise<ResolvedUpgradeVersion> {

  Line 612:     : fetchLatestFromGitHubWithSource(signal);

  Line 618: ): Promise<ResolvedUpgradeVersion | null> ...
gateway · 2026-09-09 14:27:06
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
400:     return stored.method;
401:   }
402: 
403:   // Legacy detection for existing installs (pre-setup command)
404:   const legacyMethod = await detectLegacyInstallationMethod();
405: 
406:   // Auto-save detected method for future runs (best-effort —
407:   // a read-only or broken DB shouldn't block detection)
408:   if (legacyMethod !== "unknown") {
409:     try {
410:       setInstallInfo({
411:         method: legacyMethod,
412:         path: process.execPath,
413:         version: CLI_VERSION,
414:       });
415:     } catch {
416:       log.debug("Failed to persist install info (DB may be read-only)");
417:     }
418:   }
419: 
420:   return legacyMethod;
421: }
422: 
423: // Version Fetching
424: 
425: /**
426:  * Fetch the latest version from GitHub releases. ...
gateway · 2026-09-09 14:28:05
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
85:   return LEGACY_INSTALL_SUBDIRS.map((dir) => join(homeDir, dir));
86: }
87: 
88: /**
89:  * How the CLI was installed. Determines the upgrade strategy.
90:  *
91:  * Defined here (alongside other installation constants like
92:  * {@link KNOWN_CURL_DIRS}) so that both `upgrade.ts` and
93:  * `db/install-info.ts` can import it without creating a circular
94:  * dependency.
95:  */
96: export type InstallationMethod =
97:   | "curl"
98:   | "brew"
99:   | "npm"
100:   | "pnpm"
101:   | "bun"
102:   | "yarn"
103:   | "unknown";
104: 
105: /** A repository pair that hosts CLI stable releases and nightly OCI images. */
106: export type UpgradeSource = {
107:   /** GitHub `owner/repository` containing CLI release assets. ...
gateway · 2026-09-09 14:28:18
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
285: /** Configuration for selecting the first available upgrade source. */
286: export type ResolveUpgradeSourceOptions = {
287:   /** Build the source-specific URL whose response proves source availability. */
288:   readonly getProbeUrl: (source: UpgradeSource) => string;
289:   /** Fetch implementation used for the probe. Defaults to the CLI CA-aware fetch. */
290:   readonly fetch?: typeof fetch;
291:   /** Optional cancellation signal shared by every source probe. */
292:   readonly signal?: AbortSignal;
293:   /** Ordered sources to probe. Defaults to all configured upgrade sources. */
294:   readonly sources?: readonly UpgradeSource[];
295: };
296: 
297: async function fetchUpgradeProbe(
298:   source: UpgradeSource,
299:   options: ResolveUpgradeSourceOptions
300: ): Promise<Response> {
301:   try ...
gateway · 2026-09-09 14:30:03
result
Found 22 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts:
  Line 837:         "api.github.com/repos/getsentry/toolkit/releases"

  Line 848:   test("uses the selected legacy GitHub repository", async () => {

  Line 858:       "https://api.github.com/repos/getsentry/cli/releases?per_page=12",

  Line 950:     const patchUrl = `https://github.com/getsentry/cli/releases/download/0.14.0/${binaryName}.patch`;

  Line 980:   test("keeps stable resolution on the selected legacy source", async () => {

  Line 991:       "https://api.github.com/repos/getsentry/cli/releases?per_page=12",

  Line 993:     expect(urls.every((url) => !url.includes("getsentry/toolkit"))).toBe(true);

  Line 1223:   test("keeps nightly resolution on the selected legacy source", async () => {

  Line 1239:     expect(urls).toEqual(["https://ghcr.io/v2/getsentry/cli/tags/list?n=100"]);

  Line 1240:     ...
gateway · 2026-09-09 14:30:30
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/package.json</path>
<type>file</type>
<content>
95:     "@sentry/api": "^0.256.0",
96:     "@sentry/core": "10.63.0",
97:     "@sentry/node": "10.65.0",
98:     "@sentry/node-core": "10.63.0",
99:     "@sentry/sqlish": "^1.0.1",
100:     "@sentry/symbolic": "13.7.0",
101:     "@spotlightjs/spotlight": "^4.11.7",
102:     "@stricli/auto-complete": "^1.2.8",
103:     "@stricli/core": "1.2.8",
104:     "@types/http-cache-semantics": "^4.2.0",
105:     "@types/node": "^22.20.0",
106:     "@types/picomatch": "^4.0.3",
107:     "@types/pngjs": "^6.0.5",
108:     "@types/qrcode-terminal": "^0.12.2",
109:     "@types/react": "^19.2.17",
110:     "@types/semver": "^7.7.1",
111:     "@vitest/coverage-v8": "^4.1.9",
112:     "binpatch": "^0.4.2",
113:     "chalk": "^5.6.2",
114:     "cli-highlight": "^2.1.11",
115:     "consola": "^3.4.2",
116:     "esbuild": ...
gateway · 2026-09-09 14:33:59
result
diff --git a/packages/cli/src/lib/delta-upgrade.ts b/packages/cli/src/lib/delta-upgrade.ts
index ec709b8c8..d7f2e3bfa 100644
--- a/packages/cli/src/lib/delta-upgrade.ts
+++ b/packages/cli/src/lib/delta-upgrade.ts
@@ -32,16 +32,17 @@ import {
 } from "binpatch";
 import {
   compareVersions,
-  GITHUB_RELEASES_URL,
+  getGitHubReleasesUrl,
   getPlatformBinaryName,
   isDowngrade,
   isNightlyVersion,
+  PRIMARY_UPGRADE_SOURCE,
+  type UpgradeSource,
 } from "./binary.js";
 import { CLI_VERSION } from "./constants.js";
 import { customFetch } from "./custom-ca.js";
 import { getConfigDir } from "./db/index.js";
 import { formatBytes } from "./formatters/numbers.js";
-import { GHCR_REPO } from "./ghcr.js";
 import { logger } from "./logger.js";
 import { makeByteProgress, type SetMessage } from "./progress.js";
 import { withTracing, withTracingSpan } from "./telemetry.js";
@@ -68,11 +69,15 @@ export type DeltaResult = {
   chainLength: number;
 };
 
-// GHCR publishes nightlies to ...
gateway · 2026-09-09 14:34:34
result
Found 4 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts:
  Line 575: const CHANGELOG_MAX_RELEASES = 30;

  Line 592:       `${getGitHubReleasesUrl(source)}?per_page=${CHANGELOG_MAX_RELEASES}`,

  Line 692:   const url = `https://api.github.com/repos/${source.githubRepo}/commits?sha=main&since=${sinceDate}&until=${untilDate}&per_page=100`;


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts:
  Line 263:     ? `${getGitHubReleasesUrl(source)}?per_page=100`
gateway · 2026-09-09 14:38:10
result
Found 34 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.mocked.test.ts:
  Line 29:  * Mock constants.js to pretend we're running a real stable version.

  Line 93:   test("resolves and applies a stable delta patch", async () => {

  Line 99:     // Set up fetch mocks — releases API + patch download

  Line 102:     const patchUrl = `https://github.com/getsentry/cli/releases/download/0.14.0/${BINARY_NAME}.patch`;

  Line 103:     const releases = [

  Line 105:         tag_name: "0.14.0",

  Line 110:             digest: `sha256:${versionHex("0.14.0")}`,

  Line 116:             browser_download_url: patchUrl,

  Line 148:         return new Response(JSON.stringify(releases), { status: 200 });

  Line 150:       if (urlStr === patchUrl) {

  Line 160:       // 1. Fetch releases (success)

  Line 166:         resolveStableDelta("0.14.0", oldBinaryPath, destPath)

  Line 183:         ...
gateway · 2026-09-09 14:38:22
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.mocked.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Integration tests for delta upgrade orchestration with a non-dev CLI_VERSION.
3:  *
4:  * These tests use `vi.mock()` to override `CLI_VERSION` from constants.js
5:  * so that `canAttemptDelta()` passes its dev-build guard (the real `CLI_VERSION`
6:  * is "0.0.0-dev" in test mode, which short-circuits the orchestrator).
7:  *
8:  * Kept as a sibling file to `delta-upgrade.test.ts` because its
9:  * `vi.mock()` would invert the assumptions of the dev-mode null-return
10:  * tests in that file. Under `bun test --isolate` each file gets a fresh
11:  * module graph, so the mocks here don't leak. ...
gateway · 2026-09-09 14:39:20
result
No files found
gateway · 2026-09-09 14:41:59
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts</path>
<type>file</type>
<content>
1: /** Delta upgrade discovery and application backed by binpatch. */
2: 
3: import { join } from "node:path";
4: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
5: import * as Sentry from "@sentry/node-core/light";
6: import {
7:   applyPatchChainInMemory,
8:   extractStableChain as binpatchExtractStableChain,
9:   filterAndSortChainTags as binpatchFilterAndSortChainTags,
10:   validateChainStep as binpatchValidateChainStep,
11:   type DeltaTelemetry,
12:   type DeltaUnavailableReason,
13:   type ExtractStableChainOpts,
14:   type GitHubRelease,
15:   getPatchFromVersion,
16:   getPatchTargetSha256,
17:   ghcrSource,
18:   githubReleaseSource,
19:   type InstrumentHook,
20:   MAX_NIGHTLY_CHAIN_DEPTH,
21:   makeCache,
22:   OciClient,
23:   type OciManifest,
24: ...
gateway · 2026-09-09 14:43:01
result
/**
 * GitHub Release-asset patch source (the "stable" channel).
 *
 * Resolves a patch chain from GitHub Release assets. Each release for the
 * target platform publishes three assets:
 * - `<binaryName>`        — the binary (its digest → expected SHA-256)
 * - `<binaryName>.gz`     — gzipped binary (its size → the ratio gate)
 * - `<binaryName>.patch`  — the delta patch from the previous release
 *
 * The chain is the releases between current and target, oldest-first, capped
 * at {@link MAX_STABLE_CHAIN_DEPTH} and by {@link SIZE_THRESHOLD_RATIO}.
 *
 * All product specifics (owner/repo, binary name, user-agent, fetch) are
 * injected. Generalized from Lore's stable-channel resolver.
 */

import {
  type InstrumentHook,
  MAX_STABLE_CHAIN_DEPTH,
  type PatchChain,
  type PatchLink,
  SIZE_THRESHOLD_RATIO,
} from "../contract";
import type { SourceStrategy } from "../discover";

const SHA256_DIGEST_PATTERN = /^sha256:([0-9a-f]+)$/i;

export type GitHubAsset = {
  name: string;
  ...
gateway · 2026-09-09 14:44:21
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/custom-ca.ts</path>
<type>file</type>
<content>
1: /**
2:  * Custom CA certificate loading for corporate TLS proxies.
3:  *
4:  * Reads CA bundles from (in priority order):
5:  * 1. `sentry cli defaults ca-cert` (stored path in SQLite)
6:  * 2. `NODE_EXTRA_CA_CERTS` env var
7:  *
8:  * Returns a `tls` options object for Bun's `fetch()`. On the Node.js npm
9:  * distribution, Node natively honors `NODE_EXTRA_CA_CERTS` so the extra
10:  * `tls.ca` option is harmless (ignored by Node's fetch).
11:  *
12:  * Security model: When the CA source is an env var (not a stored default)
13:  * AND the target is SaaS (`*.sentry.io`), a one-time warning is logged.
14:  * `sentry cli defaults ca-cert` silences the warning — the user has
15:  * explicitly acknowledged the custom CA. See CLI-1K6 plan for the full
16:  * threat model discussion. ...
gateway · 2026-09-09 14:44:31
result
Found 1 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/custom-ca.ts:
  Line 305: export function customFetch(
gateway · 2026-09-09 14:44:42
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/custom-ca.ts</path>
<type>file</type>
<content>
275:     "  This usually means your network uses a TLS-intercepting proxy\n" +
276:     "  (corporate firewall, VPN) with a private certificate authority.\n\n" +
277:     "  To fix this, point the CLI to your CA certificate bundle:\n" +
278:     "    sentry cli defaults ca-cert /path/to/corporate-ca.pem\n\n" +
279:     "  Or set the NODE_EXTRA_CA_CERTS environment variable:\n" +
280:     "    export NODE_EXTRA_CA_CERTS=/path/to/corporate-ca.pem"
281:   );
282: }
283: 
284: /**
285:  * Get the combined CA certificate PEM string for Node.js `http.request()`.
286:  * Returns undefined when no custom CAs are configured.
287:  *
288:  * Unlike {@link getCustomTlsOptions} (which returns Bun's `{ tls: { ca } }` shape),
289:  * this returns the raw PEM string suitable for Node's `https.RequestOptions.ca`
290:  * and ...
gateway · 2026-09-09 14:45:17
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts</path>
<type>file</type>
<content>
270:           budget: opts.sizeLimit,
271:         },
272:       }
273:     : {
274:         ok: false,
275:         failure: { reason: "missing-layer", layerName: opts.patchLayerName },
276:       };
277: }
278: 
279: export function resolveStableChain(
280:   currentVersion: string,
281:   targetVersion: string,
282:   signal?: AbortSignal,
283:   source: UpgradeSource = getPrimaryUpgradeSource()
284: ): Promise<PatchChain | null> {
285:   return stableSource(source).resolveChain(
286:     currentVersion,
287:     targetVersion,
288:     signal
289:   );
290: }
291: 
292: export async function resolveNightlyChain(opts: {
293:   token: string;
294:   currentVersion: string;
295:   targetVersion: string;
296:   fullGzSize: number;
297:   preloadedTags?: string[];
298:   signal?: AbortSignal;
299:   ...
gateway · 2026-09-09 14:46:44
result
Found 6 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts:
  Line 843:     const result = await fetchRecentReleases();

  Line 855:     await fetchRecentReleases(undefined, LEGACY_UPGRADE_SOURCE);

  Line 865:     const result = await fetchRecentReleases();

  Line 874:     const result = await fetchRecentReleases();


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts:
  Line 580:  * Uses a higher `per_page` than `fetchRecentReleases()` in delta-upgrade


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts:
  Line 160: export async function fetchRecentReleases(
gateway · 2026-09-09 14:47:02
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts</path>
<type>file</type>
<content>
760:       sizeLimit: 100_000,
761:     });
762:     expect(result).toEqual({
763:       ok: false,
764:       failure: { reason: "missing-layer", layerName: PATCH_LAYER_NAME },
765:     });
766:   });
767: 
768:   test("returns size-exceeded when layer exceeds budget", () => {
769:     const manifest = makePatchManifest("0.0.9", {}, [
770:       makeLayer(PATCH_LAYER_NAME, 200_000),
771:     ]);
772:     const result = validateChainStep(manifest, {
773:       expectedFrom: "0.0.9",
774:       patchLayerName: PATCH_LAYER_NAME,
775:       sizeLimit: 100_000,
776:     });
777:     expect(result).toEqual({
778:       ok: false,
779:       failure: {
780:         reason: "size-exceeded",
781:         layerSize: 200_000,
782:         budget: 100_000,
783:       },
784:     });
785:   });
786: 
787:   ...
gateway · 2026-09-09 14:47:32

I found the key incompatibility: source affinity is threaded through, but Toolkit stable deltas still feed raw cli@… tags to binpatch, which only compares unprefixed versions. I’m checking every stable-delta entry point and test gap before writing the final read-only report.

gpt-5.6-sol · 2026-09-09 14:47:32 · ~59 tokens
result
Found 25 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/version-check.ts:
  Line 244:       await prefetchStablePatches(latestVersion, signal, source);


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts:
  Line 1149:   return await attemptDeltaUpgrade(


/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts:
  Line 970:     const chain = await resolveStableChain("0.13.0", "0.14.0");

  Line 988:       resolveStableChain("0.13.0", "0.14.0", undefined, LEGACY_UPGRADE_SOURCE)

  Line 1039:     const chain = await resolveStableChain("0.13.0", "0.15.0");

  Line 1057:     const chain = await resolveStableChain("0.12.0", "0.14.0");

  Line 1064:     const chain = await resolveStableChain("0.12.0", "0.13.0");

  Line 1089:     ...
gateway · 2026-09-09 14:47:44
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts</path>
<type>file</type>
<content>
1110:     log.debug(`Binary verified (${formatBytes(verifiedSize)})`);
1111: 
1112:     // Clear consumed patch cache — patches for the old version are useless
1113:     // after the binary has been updated (whether via delta or full download).
1114:     // biome-ignore lint/plugin: grandfathered silent catch — see #1531; drain by adding log.debug()/log.warn() or re-throwing.
1115:     clearPatchCache().catch(() => {
1116:       /* best-effort — don't fail the upgrade if cache cleanup fails */
1117:     });
1118: 
1119:     // Set executable permission (Unix only)
1120:     if (process.platform !== "win32") {
1121:       chmodSync(tempPath, 0o755);
1122:     }
1123: 
1124:     return { tempBinaryPath: tempPath, lockPath, patchBytes };
1125:   } catch (error) {
1126:     releaseLock(lockPath);
1127:     throw ...
gateway · 2026-09-09 14:49:11
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts</path>
<type>file</type>
<content>
560:       sections.push({ category, markdown });
561:     }
562:   }
563: 
564:   return sections;
565: }
566: 
567: // ────────────────────────────── Fetch Functions ────────────────────────────
568: 
569: /**
570:  * Max releases to fetch for changelog purposes.
571:  *
572:  * Higher than the delta-upgrade cap (12) to cover larger version jumps.
573:  * GitHub API max per_page is 100; 30 covers ~6+ months of weekly releases.
574:  */
575: const CHANGELOG_MAX_RELEASES = 30;
576: 
577: /**
578:  * Fetch recent releases from GitHub for changelog building.
579:  *
580:  * Uses a higher `per_page` than `fetchRecentReleases()` in delta-upgrade
581:  * (which is capped at 12 for patch chain resolution) to cover larger
582:  * version jumps without silent truncation. ...
gateway · 2026-09-09 14:50:03
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade</path>
<type>directory</type>
<entries>
.craft.yml
.git
.github/
.gitignore
.lore.md
.nojekyll
.npmrc
AGENTS.md
apps/
CHANGELOG.md
codemods/
docs/
LICENSE.md
node_modules/
package.json
packages/
pnpm-lock.yaml
pnpm-workspace.yaml
README.md

(19 entries)
</entries>
gateway · 2026-09-09 14:50:14
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/package.json</path>
<type>file</type>
<content>
1: {
2:   "name": "sentry",
3:   "version": "0.45.0-dev.0",
4:   "description": "Sentry CLI - A command-line interface for using Sentry built by robots and humans for robots and humans",
5:   "repository": {
6:     "type": "git",
7:     "url": "git+https://github.com/getsentry/cli.git"
8:   },
9:   "main": "./dist/index.cjs",
10:   "type": "module",
11:   "types": "./dist/index.d.cts",
12:   "exports": {
13:     ".": {
14:       "import": {
15:         "types": "./dist/index.d.mts",
16:         "default": "./dist/index.mjs"
17:       },
18:       "require": {
19:         "types": "./dist/index.d.cts",
20:         "default": "./dist/index.cjs"
21:       }
22:     }
23:   },
24:   "bin": {
25:     "sentry": "./dist/bin.cjs"
26:   },
27:   "files": [
28:     "dist/bin.cjs",
29:     "dist/index.cjs",
30:     ...
gateway · 2026-09-09 14:52:10
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
180:     return cachedIsMusl;
181:   }
182: 
183:   // Heuristic 1: Check for musl dynamic linker
184:   const muslArch = process.arch === "x64" ? "x86_64" : "aarch64";
185:   if (existsSync(`/lib/ld-musl-${muslArch}.so.1`)) {
186:     cachedIsMusl = true;
187:     return true;
188:   }
189: 
190:   // Heuristic 2: ldd --version output (musl ldd writes "musl libc" to stderr)
191:   try {
192:     const result = spawnSync("ldd", ["--version"], {
193:       stdio: ["ignore", "pipe", "pipe"],
194:     });
195:     const output =
196:       Buffer.from(result.stdout).toString() +
197:       Buffer.from(result.stderr).toString();
198:     cachedIsMusl = output.toLowerCase().includes("musl");
199:     return cachedIsMusl;
200:   } catch {
201:     // ldd not found or failed — assume glibc (the common case)
202:     ...
gateway · 2026-09-09 14:52:25
result
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts</path>
<type>file</type>
<content>
95:  */
96: export type InstallationMethod =
97:   | "curl"
98:   | "brew"
99:   | "npm"
100:   | "pnpm"
101:   | "bun"
102:   | "yarn"
103:   | "unknown";
104: 
105: /** A repository pair that hosts CLI stable releases and nightly OCI images. */
106: export type UpgradeSource = {
107:   /** GitHub `owner/repository` containing CLI release assets. */
108:   readonly githubRepo: string;
109:   /** GHCR `owner/package` containing CLI nightly images and delta patches. */
110:   readonly ghcrRepo: string;
111:   /** Prefix attached to CLI release tags in this repository. */
112:   readonly tagPrefix: string;
113: };
114: 
115: /** Ordered CLI release sources. The resolver falls through only on HTTP 404. ...
gateway · 2026-09-09 14:52:41
<!-- lore-recall:608cc9fa-a0b8-4075-81a3-26e1f55091f1 --><!-- lore-recall:80c4443e-b578-4f73-bb0d-0194221e1c0c --><!-- lore-recall:baac5f45-0033-4344-a3d8-ab2b3b304f81 -->
gpt-5.6-sol · 2026-09-09 14:52:41 · ~89 tokens

Distillations (50)

Gen 0 2026-09-09 14:52:15 · 2523 tokens

- 🔴 (14:38) `packages/cli/src/lib/release-notes.ts` defines `CHANGELOG_MAX_RELEASES = 30`, requests `${getGitHubReleasesUrl(source)}?per_page=${CHANGELOG_MAX_RELEASES}`, and builds commit-history URLs as `https://api.github.com/repos/${source.githubRepo}/commits?sha=main&since=${sinceDate}&until=${untilDate}&per_page=100`. - 🔴 (14:39) `packages/cli/test/lib/delta-upgrade.mocked.test.ts` is isol…

Gen 0 2026-09-09 14:49:25 · 2930 tokens

- 🔴 (14:28) `packages/cli/src/lib/upgrade.ts` lines 433–454 define `fetchLatestFromGitHubWithSource(signal?, sources = UPGRADE_SOURCES): Promise<ResolvedUpgradeVersion>`: it calls `resolveUpgradeSource({ getProbeUrl: getGitHubLatestReleaseUrl, signal, sources })`, parses the successful response with `extractReleaseVersions(data, source)`, strips `VERSION_PREFIX_REGEX` from the first tag, throws …

Gen 0 2026-09-09 14:45:42 · 1930 tokens

- 🔴 (14:25) `packages/cli/test/lib/upgrade.test.ts` lines 591–710 test `versionExists()`: for `"curl"` version `"1.0.0"`, it first requests `https://api.github.com/repos/getsentry/toolkit/releases/tags/cli%401.0.0` and returns `true` on HTTP 200. - 🔴 (14:25) `versionExists("curl", "1.0.0")` falls back after a Toolkit HTTP 404 from `https://api.github.com/repos/getsentry/toolkit/releases/tags/cl…

Gen 0 2026-09-09 14:44:35 · 2744 tokens

- 🔴 (14:18) The `binpatch` public entrypoint describes a reusable, pure-Node (`node:*` built-ins only), zero-product-coupling binary delta-update engine with two components joined by one README wire contract: (1) an apply core that parses/applies a `TRDIFF10`/bsdiff patch chain to a binary; (2) discovery that resolves a patch chain through a pluggable `SourceStrategy` using OCI/GHCR tags or GitH…

Gen 0 2026-09-09 14:42:54 · 858 tokens

- 🔴 (14:16) `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts` lines 808–824 define `mockFetch(fn)` by assigning `globalThis.fetch`, save the original fetch in `beforeEach()`, and restore it in `afterEach()`. - 🔴 (14:16) `fetchRecentReleases()` tests verify the default GitHub API URL contains `ap…

Gen 0 2026-09-09 14:42:18 · 2129 tokens

### September 9, 2026 - 🔴 (14:11) BYK/binpatch `src/sources/github-release.ts` implements the stable-channel `githubReleaseSource()` using GitHub Release assets named `<binaryName>`, `<binaryName>.gz`, and `<binaryName>.patch`; owner/repository URL, binary name, user agent, fetch implementation, and instrumentation are injected through `GitHubReleaseSourceConfig`. - 🔴 (14:11) `extractSha256(ass…

Gen 0 2026-09-09 14:32:17 · 2568 tokens

### September 9, 2026 - 🔴 (14:07) In `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts`, `resolveContext(version, flags)` resolves `{ channel, versionArg }` through `resolveChannelAndVersion(version)`, compares against `getReleaseChannel()` to derive `channelChanged`, selects `flags.method ?? (await …

Gen 0 2026-09-09 14:29:52 · 3641 tokens

### September 9, 2026 - 🔴 (14:05) In `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts`, `getNightlyGzFilename()` returns `${getPlatformBinaryName()}.gz`. - 🔴 (14:05) `downloadNightlyToPath(destPath, version?, setMessage?, source = PRIMARY_UPGRADE_SOURCE)` gets an anonymous token for the selected `UpgradeSou…

Gen 0 2026-09-09 14:27:04 · 2471 tokens

### September 9, 2026 - 🔴 (13:56) The reviewed chain orchestration module defines `SourceStrategy.resolveChain(currentVersion, targetVersion, signal?, report?): Promise<PatchChain | null>`; a `null` result always falls back to a full download, and `report` classifications are telemetry-only and never change control flow. - 🔴 (13:56) `DeltaUnavailableReason` has exactly 5 values: `"no_patches"` …

Gen 0 2026-09-09 14:18:48 · 1494 tokens

### September 9, 2026 - 🔴 (13:44) `packages/cli/test/lib/delta-upgrade.test.ts` was 2013 lines. Its `"selected source affinity"` suite uses `importDeltaUpgradeWithVersion(version)` with `vi.resetModules()`/`vi.doMock("../../src/lib/constants.js")` and restores state via `vi.doUnmock()` plus `vi.resetModules()`. - 🔴 (13:44) Exact legacy-affinity expectations in `packages/cli/test/lib/delta-upgra…

Gen 1 2026-09-09 14:04:39 · 6110 tokens

### Current State - **Date:** September 9, 2026. - **Repository/worktree:** `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade` - **Branch:** `feat/toolkit-bridge-upgrade`; at 09:33 it was behind `origin/main` by 2 commits. - **Task:** Read-only review of Toolkit/legacy dual-source upgrade compatibility, focused on:   - `packages/cli/src/lib/…

Gen 0 2026-09-09 13:59:58 · 2548 tokens

* 🔴 (13:40) Working tree contained 18 modified files with 1,931 insertions and 325 deletions: `.github/workflows/ci.yml`, `packages/cli/install`, `packages/cli/package.json`, `packages/cli/src/commands/cli/upgrade.ts`, `packages/cli/src/lib/binary.ts`, `packages/cli/src/lib/delta-upgrade.ts`, `packages/cli/src/lib/ghcr.ts`, `packages/cli/src/lib/release-notes.ts`, `packages/cli/src/lib/upgrade.t…

Gen 0 2026-09-09 13:49:40 · 832 tokens

* 🔴 (13:37) In `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts`, the `method` flag is parsed by `parseInstallationMethod`, is optional, uses placeholder `"method"`, and is documented as supporting `curl`, `brew`, `npm`, `pnpm`, `bun`, and `yarn`. * 🔴 (13:37) The upgrade command’s `func()` calls `r…

Gen 0 2026-09-09 13:48:48 · 2879 tokens

* 🔴 (13:33) The `githubReleaseSource` stable-channel strategy models each GitHub release with three platform assets: `<binaryName>` for the expected SHA-256 digest, `<binaryName>.gz` for the full-download size ratio gate, and `<binaryName>.patch` for the delta from the previous release. * 🔴 (13:33) `extractSha256(asset)` accepts case-insensitive `sha256:([0-9a-f]+)` digests and returns lowercas…

Gen 0 2026-09-09 13:47:01 · 2380 tokens

* 🔴 (13:32) `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts` is a 648-line delta-upgrade implementation backed by `binpatch`. * 🔴 (13:32) `src/lib/delta-upgrade.ts` imports `applyPatchChainInMemory`, `extractStableChain`, `filterAndSortChainTags`, `validateChainStep`, `getPatchFromVersion`, `getPatch…

Gen 0 2026-09-09 13:44:22 · 1327 tokens

* 🔴 (13:30) In `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/version-check.test.ts`, lines 402–416 define `describe("abortPendingVersionCheck", ...)` with tests confirming `abortPendingVersionCheck()` does not throw when no check is pending and when called 3 times. * 🔴 (13:30) In `test/lib/version-check.test.ts`, …

Gen 0 2026-09-09 13:43:32 · 391 tokens

* 🔴 (13:27) User’s search found exactly 12 matches for `LEGACY_UPGRADE_SOURCE`, legacy-source affinity, and related tests in `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/delta-upgrade.test.ts`. * 🔴 (13:27) In `test/lib/delta-upgrade.test.ts`, line 46 defines `const LEGACY_UPGRADE_SOURCE = UPGRADE_SOURCES[1];`, an…

Gen 0 2026-09-09 13:43:14 · 649 tokens

* 🔴 (13:23) User’s search found exactly 47 matches for delta-upgrade resolution, execution, and prefetch APIs across 5 files under `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/`. * 🔴 (13:23) In `src/lib/version-check.ts`, line 242 calls `await prefetchNightlyPatches(latestVersion, signal, source)`, while line 244 calls `a…

Gen 0 2026-09-09 13:42:40 · 2287 tokens

* 🔴 (13:14) User showed `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/binary.ts` lines 90–279. `InstallationMethod` is `"curl" | "brew" | "npm" | "pnpm" | "bun" | "yarn" | "unknown"`, while `VALID_METHODS` accepts only `curl`, `brew`, `npm`, `pnpm`, `bun`, and `yarn`. * 🔴 (13:14) User showed `parseInstallationMetho…

Gen 0 2026-09-09 13:41:08 · 2787 tokens

* 🔴 (13:10) User showed `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/delta-upgrade.ts`, a 648-line CLI adapter around `binpatch` that preserves the existing public API while delegating chain extraction, source resolution, caching, patch application, and telemetry. * 🔴 (13:10) User showed `getPrimaryUpgradeSource()…

Gen 0 2026-09-09 13:35:54 · 2330 tokens

* 🔴 (13:08) User showed Vitest coverage for `extractSha256()`: it accepts case-insensitive `sha256:` digests and returns lowercase hex (for example, `sha256:ABCDEF01` → `abcdef01`), while missing digests and non-SHA-256 values such as `md5:deadbeef` return `null`. * 🔴 (13:08) User showed `getStableTargetSha256()` locating the exact binary asset by `name === binaryName`, extracting its SHA-256 d…

Gen 0 2026-09-09 13:30:42 · 1217 tokens

* 🔴 (13:00) User showed `packages/cli/src/commands/cli/upgrade.ts` threading optional `source?: UpgradeSource` through target resolution and upgrade execution, including `resolveExistingUpgradeVersion()`, `resolveLatestUpgradeVersion()`, `executeUpgrade()`, and returned target/done result types. * 🔴 (13:00) User showed a comment in `packages/cli/src/commands/cli/setup.ts` stating that current t…

Gen 0 2026-09-09 13:28:21 · 2307 tokens

* 🔴 (12:59) User showed source-affinity changes in `packages/cli/src/lib/delta-upgrade.ts`: `fetchRecentReleases()`, `resolveStableChain()`, `resolveNightlyChain()`, `resolveStableDelta()`, `resolveNightlyDelta()`, `attemptDeltaUpgrade()`, `prefetchNightlyPatches()`, and `prefetchStablePatches()` now accept an `UpgradeSource`, defaulting through `getPrimaryUpgradeSource()` or `PRIMARY_UPGRADE_SO…

Gen 0 2026-09-09 13:26:28 · 2361 tokens

* 🔴 (12:55) User showed `packages/cli/src/lib/delta-upgrade.ts`, a 648-line sentry-cli adapter around `binpatch` that preserves the existing public API while injecting Sentry tracing, custom CA fetch, logging, cache location, version comparison, upgrade-source configuration, and CLI progress rendering. * 🔴 (12:55) User showed `getPrimaryUpgradeSource()` returning `PRIMARY_UPGRADE_SOURCE` or thr…

Gen 0 2026-09-09 13:24:18 · 1375 tokens

* 🔴 (10:29) User showed a chain-discovery and resolve/apply orchestration module that combines a product-agnostic `SourceStrategy` with `PatchCache`, `applyPatchChainInMemory`, SHA-256 verification, and progress events; product-specific concerns such as version, telemetry, logging, and cache location are injected. * 🔴 (10:29) User defined `SourceStrategy.resolveChain(currentVersion, targetVersi…

Gen 0 2026-09-09 13:23:16 · 1920 tokens

* 🔴 (10:27) User requires `detectInstallationMethod()` in `packages/cli/src/lib/upgrade.ts` to always check Homebrew first because stored install information may be stale; `isHomebrewInstall()` is a cheap, authoritative realpath check that overrides stored data, including when a user previously had curl recorded and switched to Homebrew. * 🔴 (10:27) User showed `detectInstallationMethod()` prio…

Gen 0 2026-09-09 13:16:20 · 3221 tokens

Date: Sep 9, 2026 * 🔴 (10:22) User showed GitHub issue comment `4978828102` (`IC_kwDOQm6jAs8AAAABKMLjRg`) at `https://github.com/getsentry/cli/issues/1244#issuecomment-4978828102`: BYK, a repository MEMBER, wrote “Master tracking issue: https://github.com/getsentry/cli/issues/1248”; created and updated July 15, 2026 at 09:05:00Z, with 0 reactions. * 🔴 (10:22) User showed an in-progress change t…

Gen 0 2026-09-09 13:14:21 · 1444 tokens

Date: Sep 9, 2026 * 🔴 (10:18) User showed BYK/binpatch tags: `0.4.2` at commit `9ba6bbb8227fcbd2521852d2311c82afac5e9573`, `0.4.1` at `d0593cdd89eb720edddf9644e0753613e4a8e622`, and `0.4.0` at `2446f4cbecca92eba775e8ef52dff01fd20a9326`. * 🔴 (10:19) User showed a search with exactly 84 matches across `packages/cli/test/lib/delta-upgrade.test.ts`, `packages/cli/test/lib/delta-upgrade.mocked.test.…

Gen 0 2026-09-09 13:13:22 · 1472 tokens

* 🔴 (10:16) User showed `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts`, totaling exactly 1144 lines. * 🔴 (10:16) User showed `getNightlyGzFilename()` returns `${getPlatformBinaryName()}.gz`; nightly layers use that value as the `org.opencontainers.image.title` annotation, including `sentry-windows-x64.ex…

Gen 0 2026-09-09 13:12:23 · 1951 tokens

Date: September 9, 2026 * 🔴 (10:13) User stated that a listed patch-manifest tag failing to fetch is almost always transient (`5xx` / timeout / connection reset), whereas a poisoned tag fetches successfully with HTTP 200 and is rejected by `validateNightlyChain`. * 🔴 (10:13) User stated manifest-fetch failures must be classified as `"network"` so they never trigger a false `"malformed_chain"` p…

Gen 0 2026-09-09 13:08:34 · 989 tokens

Date: September 9, 2026 * 🔴 (10:08) User showed exactly 3 `fetchLatestFromGitHub` references: call site `packages/cli/src/lib/version-check.ts:287`, definition `packages/cli/src/lib/upgrade.ts:399`, and another call site `packages/cli/src/lib/upgrade.ts:506`. * 🔴 (10:09) User showed `packages/cli/test/lib/binary.test.ts` imports and tests `resolveUpgradeSource`, `UPGRADE_SOURCES`, and source-aw…

Gen 0 2026-09-09 13:07:55 · 2342 tokens

Date: September 9, 2026 * 🔴 (10:05) User showed the `binpatch` package is a reusable binary delta-update engine with two parts joined by one wire contract: an apply core for parsing/applying `TRDIFF10`/bsdiff patch chains, and discovery via pluggable `SourceStrategy` implementations for OCI/GHCR tags or GitHub Release assets; it uses only `node:*` built-ins and has zero product coupling. * 🔴 (1…

Gen 0 2026-09-09 13:06:26 · 997 tokens

Date: September 9, 2026 * 🔴 (10:03) User showed `SourceStrategy.resolveChain(currentVersion, targetVersion, signal?, report?)` returns `Promise<PatchChain | null>` containing an ordered oldest-hop-first patch chain and expected final SHA-256; `null` means no usable chain and always falls back to a full download. * 🔴 (10:03) User stated `UnavailableReporter` classification is telemetry-only and …

Gen 0 2026-09-09 13:05:48 · 1798 tokens

Date: September 9, 2026 * 🔴 (10:02) User showed `InstallationMethod` in `packages/cli/src/lib/binary.ts` as the exact union `"curl" | "brew" | "npm" | "pnpm" | "bun" | "yarn" | "unknown"`; `VALID_METHODS` excludes `"unknown"`, and `parseInstallationMethod()` lowercases input and throws `Invalid method: ${value}. Must be one of: ${VALID_METHODS.join(", ")}` for an unsupported method. * 🔴 (10:02)…

Gen 0 2026-09-09 13:02:57 · 2257 tokens

Date: September 9, 2026 * 🔴 (10:01) User showed additional `resolveStableChain()` coverage in `packages/cli/test/lib/delta-upgrade.test.ts`: resolving `"0.13.0"` → `"0.14.0"` returns `null`; a generated sequence of 15 releases representing 14 hops from `"0.1.0"` → `"0.15.0"` returns `null` because it exceeds `MAX_STABLE_CHAIN_DEPTH (10)`. * 🔴 (10:01) User showed `setupNightlyMocks()` in `packag…

Gen 0 2026-09-09 13:01:34 · 2638 tokens

Date: September 9, 2026 * 🔴 (09:58) User stated the Sentry CLI project is built with Node.js, pnpm, and Stricli, lives in `packages/cli` within a pnpm workspace, and has its docs site in `apps/cli-docs`. * 🔴 (09:58) User stated project goals: zero-config project-context detection from DSNs in source and env files; Seer AI-powered root-cause analysis and fix plans; developer-friendly UX followin…

Gen 0 2026-09-09 10:27:06 · 2459 tokens

* 🔴 (09:56) User showed `packages/cli/src/lib/delta-upgrade.ts` as a 627-line binpatch-backed delta-upgrade adapter importing `applyPatchChainInMemory`, `resolveAndApply`, `ghcrSource`, `githubReleaseSource`, `OciClient`, cache/discovery helpers, telemetry types, chain validators, and constants from `"binpatch"`, while preserving existing public exports such as `extractSha256`, `getPatchFromVers…

Gen 0 2026-09-09 10:24:38 · 3486 tokens

* 🔴 (09:54) User showed a diff in `packages/cli/src/lib/ghcr.ts` importing `PRIMARY_UPGRADE_SOURCE` and `type UpgradeSource` from `./binary.js`, changing `GHCR_REPO` from hard-coded `"getsentry/cli"` to `PRIMARY_UPGRADE_SOURCE.ghcrRepo`, and making GHCR token, manifest, blob, tag-listing, and layer-download helpers source-aware. * 🔴 (09:54) User showed `getAnonymousToken(sourceOrSignal, signal)…

Gen 0 2026-09-09 10:22:18 · 1967 tokens

* 🔴 (09:50) User showed GitHub comment `getsentry/cli#1244#issuecomment-4978828102` (`id: 4978828102`) by `BYK`, created and last updated `2026-07-15T09:05:00Z`, whose body is `Master tracking issue: https://github.com/getsentry/cli/issues/1248`. * 🔴 (09:51) User showed tests for `extractSha256`: a binary asset digest `sha256:ABCDEF01` becomes lowercase `abcdef01`; a missing digest or non-SHA-2…

Gen 0 2026-09-09 10:14:42 · 1637 tokens

* 🔴 (09:49) User showed a code change in `packages/cli/src/lib/binary.ts` adding `UpgradeSource = { readonly githubRepo: string; readonly ghcrRepo: string; readonly tagPrefix: string }` and the shared ordered `UPGRADE_SOURCES`: 1. `{ githubRepo: "getsentry/toolkit", ghcrRepo: "getsentry/toolkit", tagPrefix: "cli@" }`; 2. `{ githubRepo: "getsentry/cli", ghcrRepo: "getsentry/cli", tagPrefix: "" }`…

Gen 0 2026-09-09 10:13:40 · 332 tokens

* 🔴 (09:47) User showed binpatch wire-contract constants that must agree between the generator/publishing side and library: `MAX_STABLE_CHAIN_DEPTH = 10`, `MAX_NIGHTLY_CHAIN_DEPTH = 30`, `SIZE_THRESHOLD_RATIO = 0.6` for abandoning a patch chain when its total size exceeds 60% of the full gzipped download, and GHCR manifest tag prefix `PATCH_TAG_PREFIX = "patch-"`. * 🔴 (09:47) User showed shared…

Gen 0 2026-09-09 10:13:24 · 2490 tokens

* 🔴 (09:43) User showed `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:562-603`: `resolveUpdatedCliPath()` resolves `whichSync("sentry", { PATH: pathEnv }) ?? entryPath ?? execPath`; `resolveUpgradeInstallDir()` normally retains `currentInstallDir`, but relocates legacy `~/.sentry/bin` to the XDG …

Gen 0 2026-09-09 10:10:49 · 1233 tokens

* 🔴 (09:41) User specified installation-method detection in `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts` must always check Homebrew first because stored install information may be stale; the Homebrew-first check appears at line 356, before the stored-info path at line 363. * 🔴 (09:42) User stated packa…

Gen 0 2026-09-09 10:04:52 · 134 tokens

* 🟡 (09:38) Search found exactly 5 matches in `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts`: line 399 exports `fetchLatestFromGitHub(`, line 433 exports `fetchLatestFromNpm(): Promise<string>`, line 467 exports `fetchLatestNightlyVersion(`, line 503 returns `fetchLatestNightlyVersion()`, and line 506 con…

Gen 0 2026-09-09 10:03:50 · 2135 tokens

* 🔴 (09:37) User stated the binpatch library never renders progress UI; it only emits progress events. * 🟡 (09:37) The binpatch public barrel exports apply-core APIs from `./bspatch`: `addDiffChunk`, `applyPatch`, `applyPatchChainInMemory`, `applyPatchToMemory`, `MAX_OUTPUT_SIZE`, `offtin`, `parsePatchHeader`, and type `PatchHeader`. * 🟡 (09:37) The binpatch public barrel exports cache APIs fr…

Gen 0 2026-09-09 10:00:38 · 1912 tokens

* 🟡 (09:36) `src/sources/github-release.ts` defines the stable-channel `githubReleaseSource`: each GitHub release is expected to publish `<binaryName>`, `<binaryName>.gz`, and `<binaryName>.patch`; product details (`releasesUrl`, `binaryName`, `userAgent`, injectable `fetch`, and optional `InstrumentHook`) remain consumer-injected. * 🟡 (09:36) Stable SHA-256 extraction uses `SHA256_DIGEST_PATTE…

Gen 0 2026-09-09 09:49:34 · 1507 tokens

Date: Sep 9, 2026 * 🟡 (09:34) `packages/cli/test/lib/delta-upgrade.mocked.test.ts` is a 500-line integration-test file that uses `vi.mock("../../src/lib/constants.js", ...)` to set `CLI_VERSION: "0.13.0"` before importing `attemptDeltaUpgrade`, `resolveNightlyDelta`, and `resolveStableDelta`; it is separate from `delta-upgrade.test.ts` because `bun test --isolate` gives each file a fresh module …

Gen 0 2026-09-09 09:43:31 · 1597 tokens

Date: Sep 9, 2026 * 🔴 (09:33) User specified that the caller receives the successful upgrade-source probe response so it never repeats the request; only HTTP 404 advances to the next source, while every other HTTP or network failure aborts immediately. * 🔴 (09:34) User specified that the in-memory patch chain never creates scratch files on disk. * 🟡 (09:32) `downloadBinaryToTemp(version, downl…

Gen 0 2026-09-09 09:42:28 · 1117 tokens

* 🟡 (09:31) Repository search for the broader `source`/`resource` terms returned 100 matches with more available; notable upgrade-related matches were in `packages/cli/src/lib/binary.ts` and `packages/cli/src/lib/delta-upgrade.ts`. * 🟡 (09:31) Two separate file searches returned `No files found`. * 🔴 (09:32) User specified that trailing path separators may be stripped, but never from a bare ro…

Gen 0 2026-09-09 09:37:48 · 673 tokens

Date: Sep 9, 2026 * 🟡 (09:31) Repository search found 94 matches related to `binpatch` and prefetching. * 🟡 (09:31) `packages/cli/package.json` line 111 declares `"binpatch": "^0.4.2"`. * 🟡 (09:31) `packages/cli/src/lib/delta-upgrade.ts` imports `githubReleaseSource` from `binpatch`; `githubReleaseSource({ ... })` is called around line 123. * 🟡 (09:31) Delta resolution is centralized in `reso…