Dashboard › cli › Session 0Qb8hfQPd1dL
0Qb8hfQPd1dLmaAEuREAD-ONLY correctness merge-gate review, replacement reviewer, getsentry/cli PR #1569 exact base ec83887a16f780f32fba4b7d710bad262dba3a22 and head c6030fbf4d0c190f037c86d832edb6680d3e54ab. Worktree /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade. Verify immutable clean state, inspect every changed file and relevant tests. Focus on complete bridge correctness: 404-only fallback, source affinity, paginated highest SemVer, pinned --check resolution, strict and exact-bound nightly manifest annotations in resolver and final download, raw/prefetched changelog normalization, GHCR cancellation/token/redirect, stable/nightly delta/full/cache/offline, API compatibility. Intentional: nightly GitHub repository probe and source-neutral verified version-pair cache. Return NON-EMPTY findings-first report labeled PASS/CONCERN/MUST-FIX/BLOCKED, exact current file:line evidence, deterministic regression per defect, residual gaps. Final line exactly MERGE or DO-NOT-MERGE. Never modify files. Empty output is forbidden; if blocked, state exact blocker.
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/package.json /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/AGENTS.md /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/.lore.md /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/package.json /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/apps/local/package.json /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/apps/cli-docs/package.json /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/init-eval/templates/sveltekit-app/package.json /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-b...
<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. ...
No files found
<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`. ...
Found 76 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/AGENTS.md: Line 35: > **Note**: Always check `package.json` for the latest scripts. All commands run Line 55: # Testing (Vitest) Line 56: pnpm run test:unit # Run unit tests Line 57: pnpm run test:e2e # Run e2e tests Line 58: pnpm exec vitest run test/lib/foo.test.ts # Run a single test file (skips generate steps) Line 59: pnpm exec vitest # Watch mode Line 74: Node — do not reintroduce `Bun.*` globals, `bun:test`, or `bun` CLI commands.) Line 123: table below and the JSDoc in each module for details. Line 125: - **`test/`** — tests mirroring `src/` (unit, `*.property.test.ts`, Line 126: `*.model-based.test.ts`, `e2e/`, `fixtures/`, `mocks/`). ...
<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: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/.lore.md</path>
<type>file</type>
<content>
1: <!-- Managed by lore (https://github.com/BYK/loreai) — manual edits are imported on next session. -->
2:
3: ## Long-term Knowledge
4:
5: ### Architecture
6:
7: <!-- lore:01a02357-f0a8-7fdb-9e9d-b0710cfe65c9 -->
8: * **API output binary and HTTP contracts**: Always preserve strict output-mode and binary-safety contracts. `sentry api` must preserve `rawApiRequest()` status text; empty textual non-2xx bodies must produce an HTTP status/request fallback, and JSON mode must expose `{status, statusText, body}` so empty success and error responses are distinguishable. Binary `Uint8Array` successes bypass formatters and remain raw; binary errors emit only status/content-type/byte-count summaries, never bytes or JSON coercion. Prompts must never block scripted runs or interleave with stdout JSON.
9:
10: <!-- ...
c6030fbf4d0c190f037c86d832edb6680d3e54ab ec83887a16f780f32fba4b7d710bad262dba3a22 c6030fbf4d0c190f037c86d832edb6680d3e54ab f22a52690c55c6c7b472b61efe14c6af97354840d042e8f596fa31a2cd681c61 - 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.test.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.mocked.test.ts M packages/cli/test/lib/delta-upgrade.test.ts M packages/cli/test/lib/ghcr.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
...output truncated...
Full output saved to: /home/byk/.local/share/opencode/tool-output/tool_0892c0660001bpHpQDKTOlg0AH
targetVersion: target,
channel,
method,
forced: flags.force,
};
// When already on target, no update hint needed
if (CLI_VERSION !== target) {
const cmd =
versionArg && !CHANNEL_VERSIONS.has(versionArg)
? `sentry cli upgrade ${target}`
: "sentry cli upgrade";
result.warnings = [`Run '${cmd}' to update.`];
}
return result;
}
/**
* Maximum number of spawn attempts for the new binary.
*
* On Windows, Defender/SmartScreen may lock a newly-written executable for
* antivirus scanning after the file handle is closed. This causes EBUSY from
* uv_spawn. Retrying with backoff lets the scan complete without a fixed sleep.
*/
const SPAWN_MAX_ATTEMPTS = 5;
/** Base delay (ms) between spawn retry attempts. Delay = attempt * base. ...
...output truncated...
Full output saved to: /home/byk/.local/share/opencode/tool-output/tool_0892c2b51001lxS1f4KhCU3FRR
}
if (!response.ok) {
log.debug(`Nightly commits API returned ${response.status}`);
return null;
}
let commits: unknown;
try {
commits = await response.json();
} catch (parseError) {
log.debug("Non-JSON response from GitHub commits", parseError);
return null;
}
if (!Array.isArray(commits) || commits.length === 0) {
return null;
}
return buildNightlyChangelogSummary(
commits as GitHubCommit[],
fromVersion,
toVersion,
maxItems
);
}
/** Options for {@link fetchChangelog} */
export type FetchChangelogOptions = {
/** Release channel */
channel: "stable" | "nightly";
/** Current version */
fromVersion: string;
/** Target version */
toVersion: string;
/** Maximum list items to include */
maxItems?: number;
/** Pre-fetched releases to avoid redundant ...
<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. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/ghcr.ts</path>
<type>file</type>
<content>
501: * @param prefix - Optional prefix filter (e.g., "nightly-" to list versioned nightlies)
502: * @returns Array of matching tag strings
503: * @throws {UpgradeError} On network failure
504: */
505: export async function listTags(
506: token: string,
507: prefix?: string,
508: signal?: AbortSignal,
509: source: UpgradeSource = PRIMARY_UPGRADE_SOURCE
510: ): Promise<string[]> {
511: const allTags: string[] = [];
512: let lastTag: string | undefined;
513:
514: for (;;) {
515: const tags = await fetchTagPage(token, lastTag, signal, source);
516: if (tags.length === 0) {
517: break;
518: }
519:
520: for (const tag of tags) {
521: if (!prefix || tag.startsWith(prefix)) {
522: allTags.push(tag);
523: }
524: }
525:
526: if (tags.length < ...
Found 77 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:
Line 58: resolveExistingUpgradeVersion,
Line 61: versionExists,
Line 90: /** Whether the upgrade was performed offline (from cache) */
Line 91: offline?: boolean;
Line 94: /** Changelog summary for the version range. Absent for offline or on fetch failure. */
Line 101: readonly offline: boolean;
Line 138: * fetching from the network. Used by `--offline` and as automatic
Line 161: * the local cache when offline or when the network is unavailable.
Line 163: * @returns `{ target, offline }` — the resolved version and whether the
Line 164: * resolution used the offline path (explicit or automatic fallback). ...
<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. ...
Found 13 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/ghcr.test.ts: Line 92: const token = await getAnonymousToken(); Line 104: await expect(getAnonymousToken(UPGRADE_SOURCES[0])).resolves.toBe( Line 112: await expect(getAnonymousToken()).rejects.toThrow(UpgradeError); Line 113: await expect(getAnonymousToken()).rejects.toThrow( Line 123: await expect(getAnonymousToken()).rejects.toThrow(UpgradeError); Line 124: await expect(getAnonymousToken()).rejects.toThrow( Line 143: const request = getAnonymousToken(undefined, controller.signal); Line 159: await expect(getAnonymousToken()).rejects.toThrow(UpgradeError); Line 160: await expect(getAnonymousToken()).rejects.toThrow( /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts: Line 621: const token ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/ghcr.test.ts</path>
<type>file</type>
<content>
1: /**
2: * GHCR Client Tests
3: *
4: * Unit tests for the GHCR/OCI download protocol helpers.
5: * All HTTP calls are mocked via globalThis.fetch to avoid network access.
6: */
7:
8: import { afterEach, beforeEach, describe, expect, test } from "vitest";
9: import { UPGRADE_SOURCES } from "../../src/lib/binary.js";
10: import { UpgradeError } from "../../src/lib/errors.js";
11: import {
12: downloadLayerBlob,
13: downloadNightlyBlob,
14: fetchManifest,
15: fetchNightlyManifest,
16: findLayerByFilename,
17: GHCR_REPO,
18: GHCR_TAG,
19: GhcrManifestHttpError,
20: getAnonymousToken,
21: getNightlyVersion,
22: listTags,
23: type OciManifest,
24: } from "../../src/lib/ghcr.js";
25:
26: /** Store original fetch for restoration */
27: let originalFetch: typeof globalThis.fetch;
28: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/ghcr.test.ts</path>
<type>file</type>
<content>
250:
251: expect(() => getNightlyVersion(manifest)).toThrow(
252: "Nightly manifest has invalid version annotation"
253: );
254: });
255: });
256:
257: describe("findLayerByFilename", () => {
258: test("finds layer by filename annotation", () => {
259: const manifest = makeManifest();
260: const layer = findLayerByFilename(manifest, "sentry-linux-x64.gz");
261: expect(layer.digest).toBe("sha256:abc123");
262: });
263:
264: test("finds darwin layer", () => {
265: const manifest = makeManifest();
266: const layer = findLayerByFilename(manifest, "sentry-darwin-arm64.gz");
267: expect(layer.digest).toBe("sha256:def456");
268: });
269:
270: test("throws UpgradeError when filename not found", () => {
271: const manifest = makeManifest();
272: expect(() ...
<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()`. ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts</path>
<type>file</type>
<content>
521: const message = commit.message;
522:
523: if (message.includes("#skip-changelog")) {
524: continue;
525: }
526:
527: const firstLine = message.split("\n")[0]?.trim();
528: if (!firstLine) {
529: continue;
530: }
531:
532: const ccMatch = CONVENTIONAL_COMMIT_RE.exec(firstLine);
533: if (!(ccMatch?.[1] && ccMatch[2])) {
534: continue;
535: }
536:
537: const category = COMMIT_PREFIX_TO_CATEGORY.get(ccMatch[1]);
538: if (!category) {
539: continue;
540: }
541:
542: const description = ccMatch[2].trim();
543: const existing = items.get(category) ?? [];
544: existing.push(description);
545: items.set(category, existing);
546: }
547:
548: const sections: ChangeSection[] = [];
549: for (const category of ...
Found 7 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts:
Line 628: const { fromVersion, toVersion, maxItems, prefetchedReleases, source } =
Line 631: prefetchedReleases ?? (await fetchReleasesForChangelog(source));
Line 735: prefetchedReleases?: GitHubRelease[];
Line 750: export async function fetchChangelog(
Line 759: prefetchedReleases,
Line 775: prefetchedReleases,
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:
Line 873: return fetchChangelog({
Found 17 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/release-notes.test.ts:
Line 42: - Add \`sentry sourcemap inject\` and upload commands by @BYK in [#547](https://github.com/getsentry/cli/pull/547)
Line 85: expect(features!.markdown).toContain("sourcemap");
Line 303: describe("fetchChangelog source affinity", () => {
Line 316: test("fetches stable releases only from the explicitly selected Toolkit source", async () => {
Line 331: "cli@0.21.0",
Line 332: "### Bug Fixes 🐛\n\n- Keep release stages source-affine"
Line 343: source: toolkitSource,
Line 361: test("builds a Toolkit changelog from normalized prefetched releases", async () => {
Line 367: "cli@0.21.0",
Line 368: "### Bug Fixes 🐛\n\n- Reuse prefetched releases"
Line 380: source: toolkitSource,
Line 381: prefetchedReleases: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/release-notes.test.ts</path>
<type>file</type>
<content>
280: expect(extractNightlyTimestamp("not-a-version")).toBeNull();
281: expect(extractNightlyTimestamp("")).toBeNull();
282: });
283: });
284:
285: // ──────────────────── countListItems ────────────────────────────────────────
286:
287: describe("countListItems", () => {
288: test("counts items in a simple list", () => {
289: const tokens = marked.lexer("- item 1\n- item 2\n- item 3");
290: expect(countListItems(tokens)).toBe(3);
291: });
292:
293: test("returns 0 for non-list content", () => {
294: const tokens = marked.lexer("Just a paragraph.");
295: expect(countListItems(tokens)).toBe(0);
296: });
297:
298: test("returns 0 for empty token array", () => {
299: expect(countListItems([])).toBe(0);
300: });
301: });
302:
303: describe("fetchChangelog ...
<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: ...
No files found
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch</path> <type>directory</type> <entries> dist/ LICENSE package.json README.md (4 entries) </entries>
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist</path> <type>directory</type> <entries> index.d.ts index.js index.js.map (3 entries) </entries>
Found 8 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js:
Line 654: async function resolveAndApply(opts) {
Line 1038: function ghcrSource(config) {
Line 1039: const { binaryName, targetTag, compareVersions } = config;
Line 1139: () => client.fetchManifest(token, targetTag(targetVersion), signal)
Line 1225: function githubReleaseSource(config) {
Line 1227: const { releasesUrl, binaryName, userAgent } = config;
Line 1235: () => doFetch(`${releasesUrl}?per_page=${perPage}`, {
Line 1318: export { BinpatchError, MAX_NIGHTLY_CHAIN_DEPTH, MAX_OUTPUT_SIZE, MAX_STABLE_CHAIN_DEPTH, OciClient, PATCH_TAG_PREFIX, SIZE_THRESHOLD_RATIO, addDiffChunk, applyPatch, applyPatchChainInMemory, applyPatchToMemory, chainFileName, extractSha256, extractStableChain, filterAndSortChainTags, getPatchFromVersion, getPatchTargetSha256, ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js</path>
<type>file</type>
<content>
1010: let prevVersion = currentVersion;
1011: for (let i = 0; i < manifests.length; i++) {
1012: const manifest = manifests[i];
1013: const tag = chainTags[i];
1014: if (!(manifest && tag)) return { failure: "malformed_chain" };
1015: const remainingBudget = fullGzSize * SIZE_THRESHOLD_RATIO - totalSize;
1016: const result = validateChainStep(manifest, {
1017: expectedFrom: prevVersion,
1018: patchLayerName,
1019: sizeLimit: remainingBudget
1020: });
1021: if (!result.ok) {
1022: return {
1023: failure: result.reason === "over_budget" ? "over_budget" : "malformed_chain"
1024: };
1025: }
1026: digests.push(result.digest);
1027: totalSize += result.size;
1028: prevVersion = ...
Found 100 matches (more matches available)
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts:
Line 265: test("rejects GitHub release pagination outside the selected source", async () => {
Line 403: "No CLI upgrade source was found: every source returned HTTP 404"
Line 530: test("creates error with default message for offline_cache_miss", () => {
Line 531: const error = new UpgradeError("offline_cache_miss");
Line 532: expect(error.reason).toBe("offline_cache_miss");
Line 534: "Cannot upgrade offline — no pre-downloaded update is available."
Line 638: // Nightly version is now fetched from GHCR manifest annotation, not version.json
Line 650: annotations: { version: "0.0.0-dev.1740393600" },
Line 675: annotations: { version: "0.0.0-dev.1740393600" },
Line 702: test("probes prefixed Toolkit tags and retains the ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/upgrade.test.ts</path>
<type>file</type>
<content>
180: expect(parseInstallationMethod("NPM")).toBe("npm");
181: expect(parseInstallationMethod("Curl")).toBe("curl");
182: expect(parseInstallationMethod("YARN")).toBe("yarn");
183: });
184:
185: test("throws on invalid method", () => {
186: expect(() => parseInstallationMethod("pip")).toThrow("Invalid method: pip");
187: expect(() => parseInstallationMethod("apt")).toThrow("Invalid method: apt");
188: expect(() => parseInstallationMethod("")).toThrow("Invalid method: ");
189: });
190: });
191:
192: describe("fetchLatestFromGitHub", () => {
193: test("selects the latest CLI-prefixed Toolkit release", async () => {
194: const requests: string[] = [];
195: mockFetch(async (url) => {
196: requests.push(String(url));
197: return new Response(
198: ...
<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, ...
Found 81 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts:
Line 168: * Mock fetch to simulate GHCR manifest returning a specific nightly version.
Line 187: // GHCR OCI manifest for :nightly tag
Line 188: if (urlStr.includes("/manifests/nightly")) {
Line 204: return new Response("Not Found", { status: 404 });
Line 210: * Handles the latest release endpoint, version-exists check, and npm registry.
Line 231: return new Response("Not Found", { status: 404 });
Line 242: return new Response("Not Found", { status: 404 });
Line 247: * Mock fetch for the nightly version.json endpoint.
Line 250: * Mock fetch for GHCR nightly version checks (token exchange + manifest).
Line 251: * Used by nightly channel tests — replaces the old GitHub version.json mock.
Line 265: if (urlStr.includes("/manifests/nightly")) {
Line 273: ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/commands/cli/upgrade.test.ts</path>
<type>file</type>
<content>
285: );
286: mkdirSync(testDir, { recursive: true });
287: originalFetch = globalThis.fetch;
288: });
289:
290: afterEach(() => {
291: restoreStderr?.();
292: restoreStderr = undefined;
293: globalThis.fetch = originalFetch;
294: rmSync(testDir, { recursive: true, force: true });
295: });
296:
297: describe("--check mode", () => {
298: test("shows 'already on the target version' when current equals latest", async () => {
299: mockGitHubVersion(CLI_VERSION);
300:
301: const { context, getOutput, restore } = createMockContext({
302: homeDir: testDir,
303: });
304: restoreStderr = restore;
305:
306: await run(
307: app,
308: ["cli", "upgrade", "--check", "--method", "curl"],
309: context
310: ...
Found 22 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/test/lib/binary.test.ts:
Line 25: getBinaryDownloadUrl,
Line 28: getGitHubReleaseByTagUrl,
Line 36: resolveUpgradeSource,
Line 38: UPGRADE_SOURCES,
Line 43: describe("getBinaryDownloadUrl", () => {
Line 45: const url = getBinaryDownloadUrl("1.0.0");
Line 59: const url = getBinaryDownloadUrl("2.0.0");
Line 68: describe("UPGRADE_SOURCES", () => {
Line 70: expect(UPGRADE_SOURCES).toEqual([
Line 85: describe("resolveUpgradeSource", () => {
Line 89: const resolved = await resolveUpgradeSource({
Line 90: getProbeUrl: (source) => getGitHubReleaseByTagUrl("0.45.0", source),
Line 100: source: UPGRADE_SOURCES[0],
Line 111: const resolved = await resolveUpgradeSource({
Line 112: getProbeUrl: (source) => getGitHubReleaseByTagUrl("0.45.0", source),
Line 124: ...
<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: ...
85 41 packages/cli/src/commands/cli/upgrade.ts 148 6 packages/cli/src/lib/binary.ts 107 32 packages/cli/src/lib/delta-upgrade.ts 58 22 packages/cli/src/lib/ghcr.ts 81 38 packages/cli/src/lib/release-notes.ts 339 75 packages/cli/src/lib/upgrade.ts 13 8 packages/cli/src/lib/version-check.ts 13 10 packages/cli/test/commands/cli.test.ts 116 20 packages/cli/test/commands/cli/upgrade.test.ts 128 2 packages/cli/test/lib/binary.test.ts 7 7 packages/cli/test/lib/delta-upgrade.mocked.test.ts 185 16 packages/cli/test/lib/delta-upgrade.test.ts 68 5 packages/cli/test/lib/ghcr.test.ts 152 2 packages/cli/test/lib/release-notes.test.ts 478 39 packages/cli/test/lib/upgrade.test.ts 124 1 packages/cli/test/lib/version-check.test.ts
diff --git a/packages/cli/test/commands/cli.test.ts b/packages/cli/test/commands/cli.test.ts
index cd1514eb0..187ae70f4 100644
--- a/packages/cli/test/commands/cli.test.ts
+++ b/packages/cli/test/commands/cli.test.ts
@@ -107,130 +107,133 @@ describe("upgradeCommand.func", () => {
let originalFetch: typeof globalThis.fetch;
let restoreStderr: (() => void) | undefined;
beforeEach(() => {
originalFetch = globalThis.fetch;
});
afterEach(() => {
restoreStderr?.();
restoreStderr = undefined;
globalThis.fetch = originalFetch;
});
// Note: We skip testing "unknown installation method" case because
// detectInstallationMethod() runs actual shell commands (npm list, etc.)
// which can be slow/flaky in CI. The unknown method handling is tested
// indirectly through the upgrade.ts unit tests in lib/upgrade.test.ts.
test("shows installation info with specified method", async () => {
globalThis.fetch = (async () =>
- new ...
diff --git a/packages/cli/test/lib/delta-upgrade.mocked.test.ts b/packages/cli/test/lib/delta-upgrade.mocked.test.ts
index cd0a2fddc..f6186ab59 100644
--- a/packages/cli/test/lib/delta-upgrade.mocked.test.ts
+++ b/packages/cli/test/lib/delta-upgrade.mocked.test.ts
@@ -82,65 +82,65 @@ function tempFile(name: string): string {
return join(
tmpdir(),
`delta-iso-${Date.now()}-${Math.random().toString(36).slice(2)}-${name}`
);
}
// ============================================================================
// resolveStableDelta
// ============================================================================
describe("resolveStableDelta", () => {
test("resolves and applies a stable delta patch", async () => {
// Create a "current binary" to patch from
const oldBinaryPath = tempFile("old-binary.bin");
const destPath = tempFile("patched-binary.bin");
writeFileSync(oldBinaryPath, Buffer.from("old binary content for testing"));
// Set up ...
<path>/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch/dist/index.js</path>
<type>file</type>
<content>
740: return {
741: sha256,
742: patchBytes: chain.totalSize,
743: chainLength: chain.patches.length
744: };
745: }
746:
747: // src/sources/oci.ts
748: var REQUEST_TIMEOUT = 1e4;
749: var MAX_RETRIES = 1;
750: var BLOB_TIMEOUT = 3e4;
751: var TAGS_PAGE_SIZE = 100;
752: var OCI_MANIFEST_TYPE = "application/vnd.oci.image.manifest.v1+json";
753: function isRetryableError(error) {
754: if (error.name === "TimeoutError" || error.name === "AbortError") {
755: return true;
756: }
757: const msg = error.message.toLowerCase();
758: return msg.includes("timeout") || msg.includes("econnreset") || msg.includes("econnrefused") || msg.includes("network") || msg.includes("fetch failed");
759: }
760: function buildSignal(timeout, externalSignal) {
761: const timeoutSignal = ...
945adc48d962ce15e82b986e93196caabea21672 1144
...output truncated...
Full output saved to: /home/byk/.local/share/opencode/tool-output/tool_08930f9e7001Fs5HRrYVdjULLE
+ );
+ });
+
+ test("fetches stable releases only from the explicitly selected legacy source", async () => {
+ const requestedUrls: string[] = [];
+ globalThis.fetch = mockFetch(async (input) => {
+ requestedUrls.push(String(input));
+ return new Response(
+ JSON.stringify([
+ makeRelease(
+ "0.21.0",
+ "### Bug Fixes 🐛\n\n- Keep the legacy bridge working"
+ ),
+ ]),
+ { status: 200 }
+ );
+ });
+
+ const changelog = await fetchChangelog({
+ channel: "stable",
+ fromVersion: "0.20.0",
+ toVersion: "0.21.0",
+ source: legacySource,
+ });
+
+ expect(changelog?.totalItems).toBe(1);
+ expect(requestedUrls).toEqual([
+ "https://api.github.com/repos/getsentry/cli/releases?per_page=30",
+ ]);
+ });
+
+ test("fetches nightly commits only ...
Found 4 matches /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/upgrade.ts: Line 971: const response = await downloadNightlyBlob( /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/ghcr.ts: Line 364: export async function downloadNightlyBlob( Line 548: export async function downloadLayerBlob( Line 554: const response = await downloadNightlyBlob(token, digest, signal, source);
diff --git a/packages/cli/src/lib/ghcr.ts b/packages/cli/src/lib/ghcr.ts
index 43d6deb7e..f556b35fc 100644
--- a/packages/cli/src/lib/ghcr.ts
+++ b/packages/cli/src/lib/ghcr.ts
@@ -12,26 +12,31 @@
* OCI manifest holds the nightly version. Checking the latest version only
* requires a token exchange + manifest fetch (2 HTTP requests total).
* - Redirect quirk: ghcr.io blob downloads return 307 to Azure Blob Storage.
* Using `fetch` with `redirect: "follow"` would forward the Authorization
* header to Azure, which returns 404. Must follow the redirect manually
* without the auth header.
*/
+import { valid as semverValid } from "semver";
+import { PRIMARY_UPGRADE_SOURCE, type UpgradeSource } from "./binary.js";
import { getUserAgent } from "./constants.js";
import { customFetch } from "./custom-ca.js";
import { UpgradeError } from "./errors.js";
/** Default timeout for GHCR HTTP requests (10 seconds) */
const GHCR_REQUEST_TIMEOUT = 10_000;
/** Maximum ...
Found 7 matches
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/types/index.ts:
Line 212: * `write` accepts `Uint8Array` so binary command output (e.g. `sentry api`
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/dif/index.ts:
Line 6: * entirely in-process — no native binary and no dependency on the legacy Rust
Line 11: * - SEA binary: embedded asset via `node:sea.getRawAsset()`
Line 78: * In a SEA binary the bytes come from the embedded asset (fatal on error — no
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/scan/index.ts:
Line 35: } from "./binary.js";
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/index.ts:
Line 9: import { upgradeCommand } ...
TypeError: Invalid Version: cli@0.21.0
c6030fbf4d0c190f037c86d832edb6680d3e54ab f22a52690c55c6c7b472b61efe14c6af97354840d042e8f596fa31a2cd681c61 -
Raw prefetched Toolkit releases fail changelog generation.
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts:630-638 passes prefetchedReleases through unchanged, while :434-439 strips only v. A raw cli@0.21.0 tag reaches compareVersions(), which throws TypeError: Invalid Version; fetchChangelog() then silently returns null. The test at packages/cli/test/lib/release-notes.test.ts:361-388 masks this by pre-normalizing through fetchRecentReleases().
Fix: Normalize and source-filter both fetched and caller-supplied releases at one boundary, without double-stripping already normalized releases.
Regression: Pass prefetchedReleases: [makeRelease("cli@0.21.0", ...)] directly to fetchChangelog() with the Toolkit source. Assert one changelog item and no network request. Also retain coverage for already normalized prefetched releases and unrelated mcp@ tags.
Pinned resolution still depends on the unrelated latest endpoint.
/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts:322-330 always resolves latest before using the pinned target at :339-343. Therefore sentry cli upgrade --check 1.2.3 --method curl fails when latest discovery returns 403, malformed metadata, or a transport error, even when the exact cli@1.2.3 or legacy 1.2.3 tag exists. It also makes pinned nightly resolution depend on the rolling nightly manifest.
Fix: When versionArg exists, normalize and resolve that exact version directly. Never query latest. Preserve the source returned by exact resolution for changelog, delta, and download.
Regression: Make every latest endpoint fail if called, return 404 for Toolkit’s exact tag and 200 for legacy’s exact tag, then assert --check 1.2.3 succeeds, uses the legacy changelog, ...
> * 🔴 (02:43) User searched for binary/upgrade-related references and found 7 matches: `packages/cli/src/types/index.ts` line 212 (`write` accepts `Uint8Array` for binary command output such as `sentry api`); `packages/cli/src/lib/dif/index.ts` lines 6, 11, and 78 (in-process implementation without legacy Rust native binary, SEA embedded asset via `node:sea.getRawAsset()`, and fatal handling of …
* 🔴 (02:42) User’s truncated tool output was saved in full at `/home/byk/.local/share/opencode/tool-output/tool_08930f9e7001Fs5HRrYVdjULLE`. * 🔴 (02:42) User added a test named `"fetches stable releases only from the explicitly selected legacy source"` that records requested URLs and verifies stable-release requests remain confined to the explicitly selected legacy source. * 🔴 (02:42) User add…
* 🔴 (02:40) User updated `packages/cli/test/lib/delta-upgrade.mocked.test.ts` stable-delta fixtures from legacy release tags `0.14.0`/`0.13.0` to Toolkit tags `cli@0.14.0`/`cli@0.13.0`; the patch URL changed from `https://github.com/getsentry/cli/releases/download/0.14.0/${BINARY_NAME}.patch` to `https://github.com/getsentry/toolkit/releases/download/cli@0.14.0/${BINARY_NAME}.patch`. * 🔴 (02:40…
* 🔴 (02:40) User’s `UPGRADE_SOURCES` order in `packages/cli/src/lib/binary.ts` is: 1. `{ githubRepo: "getsentry/toolkit", ghcrRepo: "getsentry/toolkit", tagPrefix: "cli@" }`; 2. `{ githubRepo: "getsentry/cli", ghcrRepo: "getsentry/cli", tagPrefix: "" }`. * 🔴 (02:40) User’s `resolveUpgradeSource(...)` tests in `packages/cli/test/lib/binary.test.ts` require probing Toolkit first at `https://api.g…
Date: Sep 10, 2026 * 🔴 (02:39) User’s upgrade path-normalization code strips a trailing path separator but never strips it from a bare root such as `/`; `samePath(a: string, b: string)` compares filesystem paths while tolerating a trailing separator. * 🔴 (02:39) User’s upgrade source resolution contract states that the caller receives the successful probe response so it never repeats the succes…
* 🔴 (02:38) User’s installed `binpatch` package at `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/node_modules/binpatch` contains `dist/`, `LICENSE`, `package.json`, and `README.md`; `dist/` contains `index.d.ts`, `index.js`, and `index.js.map`. * 🔴 (02:38) User’s installed `binpatch` implementation in `/home/byk/.local/sha…
* 🔴 (02:37) User’s changelog truncation logic in `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/lib/release-notes.ts` mutates the sections array in place, replacing `markdown` with truncated markdown. * 🔴 (02:37) User’s `parseCommitMessages()` in `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a512…
Date: Sep 10, 2026 * 🔴 (02:36) User stated package managers always need network access to fetch and install packages; offline upgrades therefore only support curl-installed binaries, as enforced by `validateMethod()` in `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade/packages/cli/src/commands/cli/upgrade.ts`. * 🔴 (02:36) User’s `listTags…
* 🔴 (02:36) User requires `detectInstallationMethod()` to always check `isHomebrewInstall()` first because stored install info may be stale—for example, a previously recorded curl installation after switching to Homebrew; the realpath check is cheap and authoritative. * 🔴 (02:36) User stated `checkForUpdateInBackgroundImpl()` never throws: errors are caught and reported to Sentry. * 🔴 (02:36) …
* 🔴 (02:36) User requires `stripTrailingSep(p)` in `packages/cli/src/lib/binary.ts` to strip a trailing path separator only when `p.length > 1`, never from a bare root like `/`, so PATH entries such as `~/.local/bin/` and `~/.local/bin` compare equally. * 🔴 (02:36) User requires the GitHub source probe to return its successful response to the caller so the caller never repeats the request. * 🔴…
* 🔴 (02:35) User requires strict output-mode and binary-safety contracts for `sentry api`: preserve `rawApiRequest()` status text; empty textual non-2xx bodies must produce an HTTP status/request fallback; JSON mode must expose `{status, statusText, body}` so empty success and error responses remain distinguishable; binary `Uint8Array` successes bypass formatters and remain raw; binary errors em…
Date: Sep 10, 2026 * 🔴 [requested-review] (02:34) User requested a READ-ONLY correctness merge-gate replacement review of getsentry/cli PR #1569, pinned to exact base `ec83887a16f780f32fba4b7d710bad262dba3a22` and head `c6030fbf4d0c190f037c86d832edb6680d3e54ab`, in worktree `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade`. * 🔴 [enforced-…