Dashboard › cli › Session 0Dd6Rkxhgziq
0Dd6RkxhgziqcFhuNRead-only correctness merge gate for getsentry/cli PR #1569. Review exact immutable base ec83887a16f780f32fba4b7d710bad262dba3a22 and head 9525f72c70fabbb23ec21d13cf86add58f6287cc in /home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade. Use only git show/git diff on those SHAs; never edit or mutate VCS. Inspect every changed source and test file. Verify merge base, tree SHAs, changed paths, full diff, and diff-check. Find behavioral defects in dual-source upgrade resolution, HTTP/body error classification, source affinity, npm/GHCR validation, pagination, cancellation, pinned versions, channel/offline behavior, redirects, and delta integrity. Accepted contract: patch cache is source-neutral because dual-published artifacts are byte-identical and final output SHA-256 is verified. Return a NON-EMPTY findings-first report with exact HEAD file:line evidence. Classify each item MUST-FIX, CONCERN, or PASS; give a deterministic regression and fix for every defect. If inspection fails, report BLOCKED with exact command/error. State residual risks. Final line must be exactly MERGE or DO-NOT-MERGE.
I’ll freeze the review to the two supplied Git objects, establish ancestry and tree identity from object metadata, then inspect the complete patch and every changed source/test file. I will run only git show and git diff against immutable revisions and will not touch the worktree or VCS state.
[
{
"content": "Verify immutable base/head metadata, ancestry evidence, trees, changed paths, and diff cleanliness",
"status": "in_progress",
"priority": "high"
},
{
"content": "Inspect the full diff and every changed source and test file against the accepted upgrade contracts",
"status": "pending",
"priority": "high"
},
{
"content": "Trace edge cases and produce findings-first merge verdict with exact HEAD line evidence",
"status": "pending",
"priority": "high"
}
]
object=ec83887a16f780f32fba4b7d710bad262dba3a22 tree=110d6530e57ca4fbfb2a3f98e52013d2668b5b5e parents=e7beceb6ba09b64dc277ae1732df04e65500062b author=sentry[bot] <39604003+sentry[bot]@users.noreply.github.com> committer=GitHub <noreply@github.com> subject=fix(event): Prevent immediate retry of rate-limited org in event view fallback (#1566)
object=9525f72c70fabbb23ec21d13cf86add58f6287cc tree=22f49363a13e32c36dcd9e1ca95916809c2dc271 parents=a84012184c79c2566c7466aa6beda5f767199218 author=Burak Yigit Kaya <byk@sentry.io> committer=Burak Yigit Kaya <byk@sentry.io> subject=fix(cli): harden upgrade metadata validation
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/errors.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
packages/cli/src/commands/cli/upgrade.ts | 180 +++-- packages/cli/src/lib/binary.ts | 191 +++++- packages/cli/src/lib/delta-upgrade.ts | 170 ++++- packages/cli/src/lib/errors.ts | 8 + packages/cli/src/lib/ghcr.ts | 213 +++++- packages/cli/src/lib/release-notes.ts | 134 ++-- packages/cli/src/lib/upgrade.ts | 520 +++++++++++--- packages/cli/src/lib/version-check.ts | 21 +- packages/cli/test/commands/cli.test.ts | 40 +- packages/cli/test/commands/cli/upgrade.test.ts | 494 ++++++++++++-- packages/cli/test/lib/binary.test.ts | 188 ++++- packages/cli/test/lib/delta-upgrade.mocked.test.ts | 14 +- packages/cli/test/lib/delta-upgrade.test.ts | 220 +++++- packages/cli/test/lib/ghcr.test.ts | 235 ++++++- packages/cli/test/lib/release-notes.test.ts | 221 +++++- ...
(no output)
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/errors.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
9525f72c70fabbb23ec21d13cf86add58f6287cc tree=22f49363a13e32c36dcd9e1ca95916809c2dc271 parents=a84012184c79c2566c7466aa6beda5f767199218 fix(cli): harden upgrade metadata validation a84012184c79c2566c7466aa6beda5f767199218 tree=5f180e7390a7d23a8aad31d24d768d442ffaacbc parents=cea7b2afba91f11f1cdbb1785ea97ba61159520c fix(cli): validate upgrade response bodies cea7b2afba91f11f1cdbb1785ea97ba61159520c tree=ae3f5c1de8e1611f7f1782ec2b1053771769a1a8 parents=7d62ffa8317f9b98be0dc4afec0a927c1cabb0b7 fix(cli): validate release response shapes 7d62ffa8317f9b98be0dc4afec0a927c1cabb0b7 tree=b291f0ba3965767a808fa1eba1129f8dea9b427e parents=878459c490576dbb7abb76d3a3dc1b5d9fc62c1f fix(cli): preserve paginated request cancellation 878459c490576dbb7abb76d3a3dc1b5d9fc62c1f tree=8e36adccb73967ef42f9dc3b0015e5032ed41942 parents=e22f0eba66298a7228a988a4adcf1ec5be85227b fix(cli): fail closed on upgrade metadata e22f0eba66298a7228a988a4adcf1ec5be85227b tree=39711200f27238a7669dfd3444fa65b8701c346e ...
diff --git a/packages/cli/src/commands/cli/upgrade.ts b/packages/cli/src/commands/cli/upgrade.ts index 8d8282368307f48d894a54c6315a9c94af9f3ed2..b3039d86b5935a806f265c906460686d83ee2c64 100644 --- a/packages/cli/src/commands/cli/upgrade.ts +++ b/packages/cli/src/commands/cli/upgrade.ts @@ -1,414 +1,465 @@ /** * sentry cli upgrade * * Self-update the Sentry CLI to the latest or a specific version. * After upgrading, spawns the NEW binary with `cli setup` to update * completions, agent skills, and record installation metadata. * * Supports two release channels: * - stable (default): tracks the latest GitHub release * - nightly: tracks the rolling nightly prerelease built from main * * The channel can be set via --channel or by passing "nightly"/"stable" * as the version argument. The choice is persisted in the local database * so that subsequent bare `sentry cli upgrade` calls use the same channel. ...
diff --git a/packages/cli/src/lib/binary.ts b/packages/cli/src/lib/binary.ts
index 75582612a31fba6ee68111fcfb144f34c28eb58b..e64f5059e53d1321c3910ba46ead18391343348f 100644
--- a/packages/cli/src/lib/binary.ts
+++ b/packages/cli/src/lib/binary.ts
@@ -1,450 +1,621 @@
/**
* Binary Management
*
* Shared utilities for installing, replacing, and managing the CLI binary.
* Used by both `setup --install` (fresh installs) and `upgrade` (self-updates).
*/
import { spawnSync } from "node:child_process";
import {
existsSync,
mkdirSync,
readFileSync,
renameSync,
unlinkSync,
writeFileSync,
} from "node:fs";
import { chmod, copyFile, mkdir, realpath, unlink } from "node:fs/promises";
import { delimiter, dirname, isAbsolute, join, resolve, sep } from "node:path";
import { compare as semverCompare } from "semver";
import { getUserAgent } from "./constants.js";
import {
buildTlsErrorDetail,
customFetch,
isTlsCertError,
} from "./custom-ca.js";
-import { ...
diff --git a/packages/cli/src/lib/delta-upgrade.ts b/packages/cli/src/lib/delta-upgrade.ts
index ec709b8c8d49447c9b7a5376b61fdf19c0468f9d..204875dce4325434ff6c4b7b0fcc4d2abb9bbd50 100644
--- a/packages/cli/src/lib/delta-upgrade.ts
+++ b/packages/cli/src/lib/delta-upgrade.ts
@@ -1,388 +1,481 @@
/** Delta upgrade discovery and application backed by binpatch. */
import { join } from "node:path";
// biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
import * as Sentry from "@sentry/node-core/light";
import {
applyPatchChainInMemory,
extractStableChain as binpatchExtractStableChain,
filterAndSortChainTags as binpatchFilterAndSortChainTags,
validateChainStep as binpatchValidateChainStep,
type DeltaTelemetry,
type DeltaUnavailableReason,
type ExtractStableChainOpts,
type GitHubRelease,
getPatchFromVersion,
getPatchTargetSha256,
ghcrSource,
githubReleaseSource,
type InstrumentHook,
MAX_NIGHTLY_CHAIN_DEPTH,
...
diff --git a/packages/cli/src/lib/errors.ts b/packages/cli/src/lib/errors.ts
index f81b8c70c6c36f026b268c15b1ce16ab67e30f66..b21505cd11bdfddf7c51f0b89d942cc850ea29fe 100644
--- a/packages/cli/src/lib/errors.ts
+++ b/packages/cli/src/lib/errors.ts
@@ -521,200 +521,208 @@ export function buildValidationMessage(
note?: string
): string {
const lines = [headline];
if (examples.length > 0) {
lines.push("", "Try:");
for (const example of examples) {
lines.push(` ${example}`);
}
}
if (note) {
lines.push("", `Note: ${note}`);
}
return lines.join("\n");
}
/**
* Convenience wrapper around {@link buildValidationMessage} that returns a
* {@link ValidationError} with the given field name.
*/
export function validationError(
headline: string,
examples: string[],
field?: string,
note?: string
): ValidationError {
return new ValidationError(
buildValidationMessage(headline, examples, note),
field
);
}
/**
...
diff --git a/packages/cli/src/lib/ghcr.ts b/packages/cli/src/lib/ghcr.ts index 43d6deb7e6cf9e7911f868b757d52a6ad7d2610e..5bca7c0615a2cdd1ee956e88259d4d046e3bc97b 100644 --- a/packages/cli/src/lib/ghcr.ts +++ b/packages/cli/src/lib/ghcr.ts @@ -1,520 +1,659 @@ /** * GHCR (GitHub Container Registry) Client * * Encapsulates the OCI download protocol for fetching nightly CLI binaries * from ghcr.io/getsentry/cli. Nightly builds are pushed as OCI artifacts * via ORAS with the version baked into the manifest annotation. * * Key design decisions: * - Anonymous access: nightly package is public; no token needed beyond the * standard ghcr.io anonymous token exchange. * - Version discovery from manifest annotation: `annotations.version` in the * 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. ...
diff --git a/packages/cli/src/lib/release-notes.ts b/packages/cli/src/lib/release-notes.ts index ddf617535ea20623682cff59d28c8687aaa9e8cd..903ca51f67706a30a1e203ff1df3b288018ed3d5 100644 --- a/packages/cli/src/lib/release-notes.ts +++ b/packages/cli/src/lib/release-notes.ts @@ -1,142 +1,149 @@ /** * Release Notes Parser & Aggregation * * Extracts user-facing changelog entries from GitHub Release bodies (stable) * or conventional commit messages (nightly). Uses `marked.lexer()` for * AST-based section extraction and produces structured data that can be * re-serialized as filtered markdown for rendering via `renderMarkdown()`. ...
diff --git a/packages/cli/src/lib/upgrade.ts b/packages/cli/src/lib/upgrade.ts index 945adc48d962ce15e82b986e93196caabea21672..b29d67ff2da3f1ba4940ec971aa9b11f41ed390f 100644 --- a/packages/cli/src/lib/upgrade.ts +++ b/packages/cli/src/lib/upgrade.ts @@ -1,209 +1,307 @@ /** * Upgrade Module * * Detects how the CLI was installed and provides self-upgrade functionality. * Binary management helpers (download URLs, locking, replacement) live in * binary.ts and are shared with the setup --install flow. ...
diff --git a/packages/cli/src/lib/version-check.ts b/packages/cli/src/lib/version-check.ts
index c69ff04663447b2ae2ce62093b527554983c1568..34393b1c777e09c0a1ab683a493a6f15d91811c3 100644
--- a/packages/cli/src/lib/version-check.ts
+++ b/packages/cli/src/lib/version-check.ts
@@ -1,411 +1,416 @@
/**
* Background version check for "new version available" notifications.
*
* For nightly builds (CLI_VERSION contains "-dev.<timestamp>"), checks GHCR for the
* latest nightly version via the OCI manifest annotation. For stable builds,
* checks GitHub Releases. Results are cached in the database and shown on
* subsequent runs.
*/
// biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
import * as Sentry from "@sentry/node-core/light";
import { compare as semverCompare } from "semver";
+import type { UpgradeSource } from "./binary.js";
import { CLI_VERSION } from "./constants.js";
import { getReleaseChannel } from ...
The immutable history is a linear 19-commit chain whose first commit directly parents the supplied base; direct and three-dot path sets match, so the merge base is ec83887…. The patch changes 17 files, and git diff --check is clean; I’m now testing the implementation against its source-affinity and failure-classification contracts rather than treating coverage as proof.
[
{
"content": "Verify immutable base/head metadata, ancestry evidence, trees, changed paths, and diff cleanliness",
"status": "completed",
"priority": "high"
},
{
"content": "Inspect the full diff and every changed source and test file against the accepted upgrade contracts",
"status": "in_progress",
"priority": "high"
},
{
"content": "Trace edge cases and produce findings-first merge verdict with exact HEAD line evidence",
"status": "pending",
"priority": "high"
}
]
diff --git a/packages/cli/test/lib/binary.test.ts b/packages/cli/test/lib/binary.test.ts
index 6fcfb3b1aa34cb1caaf27b3060bb40522bd3eccf..29ead382894204b9d973efb72792d49543fa2c1a 100644
--- a/packages/cli/test/lib/binary.test.ts
+++ b/packages/cli/test/lib/binary.test.ts
@@ -20,34 +20,39 @@ import { afterEach, beforeEach, describe, expect, test } from "vitest";
import {
acquireLock,
compareVersions,
determineInstallDir,
fetchWithUpgradeError,
getBinaryDownloadUrl,
getBinaryFilename,
getBinaryPaths,
+ getGitHubReleaseByTagUrl,
getLegacyInstallDirs,
getPlatformBinaryName,
installBinary,
isDowngrade,
isMusl,
+ parseUpgradeJson,
releaseLock,
replaceBinarySync,
+ resolveUpgradeSource,
samePath,
+ UPGRADE_SOURCES,
+ UpgradeSourceNotFoundError,
} from "../../src/lib/binary.js";
import { UpgradeError } from "../../src/lib/errors.js";
describe("getBinaryDownloadUrl", () => {
test("builds correct URL for current platform", () => {
...
diff --git a/packages/cli/test/lib/ghcr.test.ts b/packages/cli/test/lib/ghcr.test.ts
index e5c81d5324971e3c0f75c141d2cdb081d2ba3eb6..a55612b5af0c69d4fc60039c97d6e1eeabe77b71 100644
--- a/packages/cli/test/lib/ghcr.test.ts
+++ b/packages/cli/test/lib/ghcr.test.ts
@@ -1,25 +1,27 @@
/**
* GHCR Client Tests
*
* Unit tests for the GHCR/OCI download protocol helpers.
* All HTTP calls are mocked via globalThis.fetch to avoid network access.
*/
import { afterEach, beforeEach, describe, expect, test } from "vitest";
+import { UPGRADE_SOURCES } from "../../src/lib/binary.js";
import { UpgradeError } from "../../src/lib/errors.js";
import {
downloadLayerBlob,
downloadNightlyBlob,
fetchManifest,
fetchNightlyManifest,
findLayerByFilename,
GHCR_REPO,
GHCR_TAG,
+ GhcrManifestHttpError,
getAnonymousToken,
getNightlyVersion,
listTags,
type OciManifest,
} from "../../src/lib/ghcr.js";
/** Store original fetch for restoration */
let originalFetch: ...
diff --git a/packages/cli/test/lib/release-notes.test.ts b/packages/cli/test/lib/release-notes.test.ts
index 78963b47163a371015dfa190af14d24e6595fe23..ffccf49016b3c37ec9fcb9f0ada57753ee9f5986 100644
--- a/packages/cli/test/lib/release-notes.test.ts
+++ b/packages/cli/test/lib/release-notes.test.ts
@@ -4,26 +4,32 @@
* Tests core invariants (section extraction, version filtering, truncation)
* that are hard to express as property-based tests due to format specifics.
*
* Core random-input invariants (category validity, filtering, commit parsing)
* are tested via property-based tests in release-notes.property.test.ts.
*/
import { marked } from "marked";
-import { describe, expect, test } from "vitest";
-import type { GitHubRelease } from "../../src/lib/delta-upgrade.js";
+import { afterEach, beforeEach, describe, expect, test } from "vitest";
+import { UPGRADE_SOURCES } from "../../src/lib/binary.js";
+import {
+ fetchRecentReleases,
+ type GitHubRelease,
+} from ...
diff --git a/packages/cli/test/lib/version-check.test.ts b/packages/cli/test/lib/version-check.test.ts
index 20172cd83922569cfc1d9823b8285d9f539e1767..dd047a5cb589b4442b34fcb6e9d653e808fb5bb3 100644
--- a/packages/cli/test/lib/version-check.test.ts
+++ b/packages/cli/test/lib/version-check.test.ts
@@ -1,19 +1,22 @@
/**
* Version Check Logic Tests
*/
import { setTimeout as sleep } from "node:timers/promises";
-import { afterEach, beforeEach, describe, expect, test } from "vitest";
+import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
+import { UPGRADE_SOURCES } from "../../src/lib/binary.js";
import { setReleaseChannel } from "../../src/lib/db/release-channel.js";
import {
getVersionCheckInfo,
setVersionCheckInfo,
} from "../../src/lib/db/version-check.js";
+// biome-ignore lint/performance/noNamespaceImport: Vitest requires the module namespace to spy on an ESM export
+import * as deltaUpgrade from "../../src/lib/delta-upgrade.js";
import {
...
diff --git a/packages/cli/test/lib/delta-upgrade.mocked.test.ts b/packages/cli/test/lib/delta-upgrade.mocked.test.ts
index cd0a2fddc29722048fa5f8ec0efa268406242e08..f6186ab59706e32b5624f094934060e99805738f 100644
--- a/packages/cli/test/lib/delta-upgrade.mocked.test.ts
+++ b/packages/cli/test/lib/delta-upgrade.mocked.test.ts
@@ -94,20 +94,20 @@ describe("resolveStableDelta", () => {
// 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 fetch mocks — releases API + patch download
// Since applyPatch will fail (we don't have a real TRDIFF10 matching this binary),
// we expect resolveStableDelta to throw, but the chain resolution should succeed
- const patchUrl = `https://github.com/getsentry/cli/releases/download/0.14.0/${BINARY_NAME}.patch`;
+ const patchUrl = ...
diff --git a/packages/cli/test/lib/delta-upgrade.test.ts b/packages/cli/test/lib/delta-upgrade.test.ts
index 3752d4ae67fc6df165f018dd3e2b1a9501b13ae6..68d1cfbdfe2a39fdd2f91a1540c9a8b31e3ca8e2 100644
--- a/packages/cli/test/lib/delta-upgrade.test.ts
+++ b/packages/cli/test/lib/delta-upgrade.test.ts
@@ -6,18 +6,21 @@
* async orchestration functions tested via fetch mocking.
*/
import { createHash } from "node:crypto";
import { existsSync, unlinkSync } from "node:fs";
import { access, readFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
-import { afterEach, beforeEach, describe, expect, test } from "vitest";
-import { getPlatformBinaryName } from "../../src/lib/binary.js";
+import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
+import {
+ getPlatformBinaryName,
+ UPGRADE_SOURCES,
+} from "../../src/lib/binary.js";
import {
applyPatchChain,
attemptDeltaUpgrade,
canAttemptDelta,
...
diff --git a/packages/cli/test/commands/cli.test.ts b/packages/cli/test/commands/cli.test.ts
index cd1514eb0c2f3c5db5d5ac9bed0f2d37be35de13..4eec11e9d8fa20ef1c55738a82df0a7f3bbad6bd 100644
--- a/packages/cli/test/commands/cli.test.ts
+++ b/packages/cli/test/commands/cli.test.ts
@@ -117,120 +117,114 @@ describe("upgradeCommand.func", () => {
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 Response(JSON.stringify({ tag_name: "v0.0.0-dev" }), {
+ new Response(JSON.stringify([{ tag_name: "cli@1.0.0" }]), {
status: 200,
headers: { "Content-Type": ...
diff --git a/packages/cli/test/commands/cli/upgrade.test.ts b/packages/cli/test/commands/cli/upgrade.test.ts
index ca9688e46730b0cb31a85c9538a65a2eca1e004c..b7fead58fbef43936ca22d8e4901000961ce740d 100644
--- a/packages/cli/test/commands/cli/upgrade.test.ts
+++ b/packages/cli/test/commands/cli/upgrade.test.ts
@@ -38,10 +38,11 @@ import {
} from "../../../src/lib/db/install-info.js";
import {
getReleaseChannel,
setReleaseChannel,
} from "../../../src/lib/db/release-channel.js";
+import { setVersionCheckInfo } from "../../../src/lib/db/version-check.js";
import { TEST_TMP_DIR, useTestConfigDir } from "../../helpers.js";
/** Store original fetch for restoration */
let originalFetch: typeof globalThis.fetch;
@@ -170,10 +171,14 @@ function createMockContext(
*/
function mockGhcrNightlyVersion(version: string): void {
mockFetch(async (url) => {
const urlStr = String(url);
+ if (urlStr === "https://api.github.com/repos/getsentry/toolkit") {
+ return new ...
* 🔴 (11:48) User provided changes in `packages/cli/src/lib/binary.ts` that import and use `UpgradeTransportError` from `./errors.js` for upgrade transport failures. * 🔴 (11:48) User specified `stripTrailingSep(p: string)` strips one trailing platform path separator only when `p.length > 1`, so equivalent PATH entries such as `~/.local/bin/` and `~/.local/bin` compare equally while a bare root l…
Date: Sep 10, 2026 * 🟡 (11:46) Review tracking showed 3 ordered tasks: 1. Verify immutable base/head metadata, ancestry evidence, trees, changed paths, and diff cleanliness (`in_progress`, high priority); 2. Inspect the full diff and every changed source and test file against accepted upgrade contracts (`pending`, high priority); 3. Trace edge cases and produce a findings-first merge verdict wit…
🔴 (11:45) User directed that the review of getsentry/cli PR #1569 is strictly read-only: use only `git show`/`git diff` on the supplied SHAs and never edit the worktree or mutate VCS. 🟡 (11:45) [requested-review] User requested a correctness merge gate for getsentry/cli PR #1569 in `/home/byk/.local/share/opencode/worktree/0e8c2f3bbe145a3280d6fb6ed900a5121f382cf0/toolkit-bridge-upgrade`, review…