From d5bfd82cde8e4133edb0b296792e079930665319 Mon Sep 17 00:00:00 2001 From: Kameron Smith <112618179+nullStack65@users.noreply.github.com> Date: Sat, 31 Oct 2026 07:05:53 -0400 Subject: [PATCH 1/3] docs: map fork behavior for V2 convergence --- docs/internals/v2-fork-convergence-draft.md | 50 +++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 docs/internals/v2-fork-convergence-draft.md diff --git a/docs/internals/v2-fork-convergence-draft.md b/docs/internals/v2-fork-convergence-draft.md new file mode 100644 index 0000000000000..822fb5c2a8d6b --- /dev/null +++ b/docs/internals/v2-fork-convergence-draft.md @@ -0,0 +1,50 @@ +# Draft: fork main and V2 convergence + +This file is a temporary review carrier for an explicitly requested draft planning PR. It is not a proposed permanent repository document and must be removed or replaced by reviewed implementation before any landing. This branch does not implement or authorize runtime adoption, a release, deployment, or a workflow run. + +## Frozen comparison + +- Fork main: `405f47c189187aa401821763c69c5e273de32831`, tree `12456a0f25c122faf9f91ba55c3a89a4af85a2d5`. +- Held V2 branch: `2f521e6d214512dc573df82c1d143405245439c9`, installed Nightly provenance `3417bc3856a25fa772f969faeaf8428a58010d47`. The branch tip is source, not proof of installed adoption. +- Common ancestor `d7819c18813fa03b033cc1c9472c9acc0ffc0618`; V2 is 1,230 commits ahead and 58 fork-main commits behind. Compare all 58 commits, including individual commits within merge PRs, not just the PR subjects. This matrix groups those commits by their owning PR, not by an assertion that they can be dropped. +- GitHub current branch readback confirmed these refs on 2026-10-31. Re-read them before composition. No existing PR or branch is superseded by this document. + +## Preservation matrix + +Status “map” means behavior and a V2 execution path still need source-level mapping and tests; no equivalence is implied by a similar name. + +| Main source / commits | Main paths and intent | Held V2 / required disposition | +| --- | --- | --- | +| #3 `bcc1a58b` | `packages/contracts/src/settings.ts`, `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`, settings/search/action UI: default-on title preference; disabling must suppress initial, refinement and manual LLM calls, preserve first-prompt title, and restore defaults. | Confirmed absent from held settings. Map all V2 title-generation and regeneration paths, pending-state clearing, UI and scoped settings; test all three suppression paths and defaults. | +| #4 `b423938f`, #6 `f5d3fc66` and their component commits | `apps/server/src/usage/*`, provider-session persistence/migrations and route metadata: measured attribution, explicit unknowns, shared/orphan accounting, durable canary route identity through resumes/retries. | Map V2 event and session identities, migration and projection evidence; reproduce reconciliation and unknown-vs-zero cases without claiming inferred attribution. | +| #5 `419f7574`, #19 `23467c59`, #20 `eb5d08c3`, #24 `cb9636bf`, #25 `59152d9d`, #26 `e3ff4410` and component commits | Fork release/update isolation, source and artifact provenance, candidate verification, digest-bound frozen manifest, promotion, staging, installers and workflows under `scripts/`, `.github/workflows/`, `packages/shared/src/cliRelease.ts`. | Confirmed held CLI index defaults to `pingdotgg/t3code`; `scripts/lib/fork-promotion.ts` is absent. Restore fork index/download and override behavior and verify every packaging/install consumer. Adapt release machinery to V2 packaging, preserving source ancestry of fork main, candidate-specific frozen-manifest approval, exact source/digests and no-overwrite/fail-closed publication. Preserve held #39 builder preflight. No release or promotion execution. | +| #7 `7a2b41e7` | `apps/server/src/orchestration/ThreadPostStartActivity.ts`, `packages/shared/src/postStartActivity.ts`, client runtime, web/mobile: live progress, wait/disconnect/silence, stale-turn fences and monotonic observation receipts. | Legacy server path absent. Map V2 run/event lifecycles and each client/connection mode; test silence vs known waits, stale traffic, resumption and terminal clearing. | +| #10 `55814122` | `native/windows-service-host/`, `apps/server/src/cloud/windowsBootService.ts` and launcher: SCM host, JobObject, graceful stop and exact owned binding. | Native host absent at same path. Establish faithful lifecycle/ownership behavior against V2 launch, and retain portable, Windows-target and real native qualification boundaries. | +| #11 `404501a0` | `apps/server/src/environment/LaunchPreflight.ts` and launch integration: bounded read-only preflight, warning delivery and narrow demonstrated blocking case. | Legacy path absent. Map V2 launch, provider start and activity delivery, including shared-root and Git capability cases, without broadening blocks or bypassing warnings. | +| #13 `08dbb72d`, #15 `131538a8` | OpenCode missing-session continuation refuses silent replacement; Codex proxy catalogs are instance-scoped, default preserved. Legacy provider adapters and `packages/contracts/src/settings.ts`. | Map the V2 adapters and instance settings; tests must prove missing-session failure and cross-instance catalog isolation. | +| #16 `0399d919`, #18 `58de9088` | `apps/server/src/auth/EnvironmentAuth.ts`, `packages/contracts/src/auth.ts`, `packages/contracts/src/providerIdentity.ts`: optional stable session subject; managed identity qualification and exact drift, never credential disclosure. | Verify transport and V2 registry/contract counterparts; preserve fail-closed identity and compatibility. No new identity authority or access expansion. | +| #17 `0975683e`, #23 `170c0fab` | Hosted CI adaptations, repository-neutral mirrors, tooling declarations; `AGENTS.md` requires isolated synthetic test data and forbids copying real userdata. | Reconcile workflow differences and maintain fixture instruction; no workflow setting changes or Action runs. Empty checks are not green. | +| #21 `fdfab8dc`, #22 `eca73bdf` | Callback route serialized admission and effect fence; `apps/server/src/pullRequest/PullRequestService.ts` owner-only reviewer mutation. | Map both to V2 serialized admission/effect and source-control service. Prove rejected callback leaves no persisted message/turn and reviewer policy retains its existing owner-only boundaries. | +| #31 `47947cb5`, #33 `d740e35e`, #35 `9ebc81ad`, #37 `e97641ab` | Governed Codex opt-in, native observation, reader/account fences and fresh typed Skill inputs. | V2 adaptation #38 is already in held `c98aebb4`; #39 is held `2f521e6d`; #46 is the separately owned open composition with telemetry. Review semantic preservation and their current exact heads; do not duplicate the legacy adapter. | +| #32 `9d839566` | `.github/workflows/deploy-relay.yml`, `apps/server/scripts/deploy-relay-workflow.test.ts`: only first-attempt owner dispatch on current main, reviewed source equals workflow and current main, read-only admission before production credentials. | Held workflow has push-to-main and wider status permission. Preserve every #32 admission condition, production environment and credential boundaries; reconcile newer held workflow details without opening production access. Never execute it here. | +| #48 `405f47c1` | `apps/server/src/provider/testFixtures/claudeTildeMock.mjs` and registry tests: clear fixture keepalive at EOF, natural output drain, normal and 128-KiB cases. | Both legacy paths absent in held. Locate modern equivalents and reproduce leak or justify absence across fixture creation paths; absence of this filename alone is not proof. | + +This list classifies the 58 comparison commits under their integration PRs; it is an audit starting point, not a finding that any behavior is already preserved. Inspect additional upstream/V2 changes, instructions and path-specific ownership when resolving each item. + +## Other open work and integration boundaries + +- #34 → #42 → #43 → #44 → #45 and #46 remain their owners' source stack. #46 composes governed submission and telemetry; do not take a shortcut around the originals or claim their source accepted. #44 requires exact candidate and compatible rollback-reader replay/rebuild/recovery before live emission. +- #36 → #40 is separately owned; #40 diverges from held tip and must preserve #39. #28 is separately owned and its legacy 55-path composed-tree qualification does not establish V2 launch, send, persistence, retry, web/Electron or native mobile equivalence. #1, #2, #29, #30, #41 and #47 also remain open and need owner-specific disposition, not automatic closure. +- [#34 plan](https://github.com/nullStack65/t3code/pull/34#issuecomment-6542458467) and [#28 qualification](https://github.com/nullStack65/t3code/pull/28#issuecomment-6542416458) are evidence for their stated trees and limits only. + +## Proposed minimal sequencing + +1. Refresh refs and inventory all open work and exact 58 commits, owners and path overlaps. Freeze source identities and compile a traceable behavior/test matrix; do not mutate existing branches or main. +2. In an isolated candidate, compose normal Git history with both current main and the reviewed V2 lineage as parents. Resolve changes by behavior, not wholesale tree selection. First preserve relay admission, fork update isolation, promotion/provenance and synthetic data rules; no privilege or production access expansion. These protections are merge blockers throughout, even while Actions are disabled. +3. Port or prove each remaining fork behavior on real V2 seams, with targeted regressions and review of shared paths. Carry #38/#39, then integrate each owned open source stack only through its owner and its own qualification. Keep #28 and watcher conflicts explicit. +4. Validate exact candidate commit and complete tree using pinned tools and isolated synthetic data. Reconcile browser/Electron/mobile and Windows-native evidence using the repository's supported tools; if unavailable, stop that verification and report it. Re-read branch rules and exact-head checks; an empty check list does not prove CI green. +5. Root coordinates independent review, normal merge window, rollback compatibility and any separately authorized artifact/build/install work. Source readiness alone is not activation. + +## Current blockers and evidence + +This task's local checkout is at `e97641abf69fb88538b53279ded28704b6ccb2b3` and lacks both frozen tip objects. Fetching them over the inherited proxy returned HTTP 503; cloud status reports failed Tailscale enrollment and blocks non-platform network. GitHub connector read-only comparisons and file inspection worked, but no combined tree or tests were produced. The connector's branch summary reports main unprotected and no required checks; rulesets read empty, while direct branch-protection read returned 403 for this integration. Recheck with sufficient visibility before any merge. No claims about Actions, native acceptance or production readiness follow from those reads. From 38f17648c01e0c4ea99bc2cc4dcd4e4d191d2000 Mon Sep 17 00:00:00 2001 From: Kameron Smith <112618179+nullStack65@users.noreply.github.com> Date: Sat, 31 Oct 2026 07:09:35 -0400 Subject: [PATCH 2/3] docs: record V2 preservation evidence --- docs/internals/v2-fork-convergence-draft.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/internals/v2-fork-convergence-draft.md b/docs/internals/v2-fork-convergence-draft.md index 822fb5c2a8d6b..a2e39bac23cbd 100644 --- a/docs/internals/v2-fork-convergence-draft.md +++ b/docs/internals/v2-fork-convergence-draft.md @@ -15,7 +15,7 @@ Status “map” means behavior and a V2 execution path still need source-level | Main source / commits | Main paths and intent | Held V2 / required disposition | | --- | --- | --- | -| #3 `bcc1a58b` | `packages/contracts/src/settings.ts`, `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`, settings/search/action UI: default-on title preference; disabling must suppress initial, refinement and manual LLM calls, preserve first-prompt title, and restore defaults. | Confirmed absent from held settings. Map all V2 title-generation and regeneration paths, pending-state clearing, UI and scoped settings; test all three suppression paths and defaults. | +| #3 `bcc1a58b` | `packages/contracts/src/settings.ts`, `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`, settings/search/action UI: default-on title preference; disabling must suppress initial, refinement and manual LLM calls, preserve first-prompt title, and restore defaults. | Confirmed absent from held settings. `ThreadLaunchService.ts` supplies `titleSeed`; `Orchestrator.ts` arms title generation; `EffectWorker.ts` invokes `ThreadTitleRegenerationService.ts`, which resolves project settings then calls `generateThreadTitle`. Add the preference at the shared V2 service boundary while preserving completion of pending state; inspect all initial/refinement/regenerate call paths, UI, defaults and scoped settings, then test each. | | #4 `b423938f`, #6 `f5d3fc66` and their component commits | `apps/server/src/usage/*`, provider-session persistence/migrations and route metadata: measured attribution, explicit unknowns, shared/orphan accounting, durable canary route identity through resumes/retries. | Map V2 event and session identities, migration and projection evidence; reproduce reconciliation and unknown-vs-zero cases without claiming inferred attribution. | | #5 `419f7574`, #19 `23467c59`, #20 `eb5d08c3`, #24 `cb9636bf`, #25 `59152d9d`, #26 `e3ff4410` and component commits | Fork release/update isolation, source and artifact provenance, candidate verification, digest-bound frozen manifest, promotion, staging, installers and workflows under `scripts/`, `.github/workflows/`, `packages/shared/src/cliRelease.ts`. | Confirmed held CLI index defaults to `pingdotgg/t3code`; `scripts/lib/fork-promotion.ts` is absent. Restore fork index/download and override behavior and verify every packaging/install consumer. Adapt release machinery to V2 packaging, preserving source ancestry of fork main, candidate-specific frozen-manifest approval, exact source/digests and no-overwrite/fail-closed publication. Preserve held #39 builder preflight. No release or promotion execution. | | #7 `7a2b41e7` | `apps/server/src/orchestration/ThreadPostStartActivity.ts`, `packages/shared/src/postStartActivity.ts`, client runtime, web/mobile: live progress, wait/disconnect/silence, stale-turn fences and monotonic observation receipts. | Legacy server path absent. Map V2 run/event lifecycles and each client/connection mode; test silence vs known waits, stale traffic, resumption and terminal clearing. | @@ -24,10 +24,10 @@ Status “map” means behavior and a V2 execution path still need source-level | #13 `08dbb72d`, #15 `131538a8` | OpenCode missing-session continuation refuses silent replacement; Codex proxy catalogs are instance-scoped, default preserved. Legacy provider adapters and `packages/contracts/src/settings.ts`. | Map the V2 adapters and instance settings; tests must prove missing-session failure and cross-instance catalog isolation. | | #16 `0399d919`, #18 `58de9088` | `apps/server/src/auth/EnvironmentAuth.ts`, `packages/contracts/src/auth.ts`, `packages/contracts/src/providerIdentity.ts`: optional stable session subject; managed identity qualification and exact drift, never credential disclosure. | Verify transport and V2 registry/contract counterparts; preserve fail-closed identity and compatibility. No new identity authority or access expansion. | | #17 `0975683e`, #23 `170c0fab` | Hosted CI adaptations, repository-neutral mirrors, tooling declarations; `AGENTS.md` requires isolated synthetic test data and forbids copying real userdata. | Reconcile workflow differences and maintain fixture instruction; no workflow setting changes or Action runs. Empty checks are not green. | -| #21 `fdfab8dc`, #22 `eca73bdf` | Callback route serialized admission and effect fence; `apps/server/src/pullRequest/PullRequestService.ts` owner-only reviewer mutation. | Map both to V2 serialized admission/effect and source-control service. Prove rejected callback leaves no persisted message/turn and reviewer policy retains its existing owner-only boundaries. | +| #21 `fdfab8dc`, #22 `eca73bdf` | Callback route serialized admission and effect fence; `apps/server/src/pullRequest/PullRequestService.ts` owner-only reviewer mutation. | Map callback handling to V2 serialized admission/effect. Held `apps/server/src/pullRequest/PullRequestService.ts` lines 2486–2516 forwards requested reviewers after checking generic viewer permission; that function contains no owner-only filter. Trace all callers and the underlying adapter, then carry #22's verified GitHub owner-only admission and removal behavior without broadening it. Prove rejected callback leaves no persisted message/turn. | | #31 `47947cb5`, #33 `d740e35e`, #35 `9ebc81ad`, #37 `e97641ab` | Governed Codex opt-in, native observation, reader/account fences and fresh typed Skill inputs. | V2 adaptation #38 is already in held `c98aebb4`; #39 is held `2f521e6d`; #46 is the separately owned open composition with telemetry. Review semantic preservation and their current exact heads; do not duplicate the legacy adapter. | | #32 `9d839566` | `.github/workflows/deploy-relay.yml`, `apps/server/scripts/deploy-relay-workflow.test.ts`: only first-attempt owner dispatch on current main, reviewed source equals workflow and current main, read-only admission before production credentials. | Held workflow has push-to-main and wider status permission. Preserve every #32 admission condition, production environment and credential boundaries; reconcile newer held workflow details without opening production access. Never execute it here. | -| #48 `405f47c1` | `apps/server/src/provider/testFixtures/claudeTildeMock.mjs` and registry tests: clear fixture keepalive at EOF, natural output drain, normal and 128-KiB cases. | Both legacy paths absent in held. Locate modern equivalents and reproduce leak or justify absence across fixture creation paths; absence of this filename alone is not proof. | +| #48 `405f47c1` | `apps/server/src/provider/testFixtures/claudeTildeMock.mjs` and registry tests: clear fixture keepalive at EOF, natural output drain, normal and 128-KiB cases. | The held equivalent `apps/server/src/provider/testing/ClaudeCapabilitiesProbe.fixture.mjs` (blob `57fc1795cb65e3601198f3abef3d7ad37ee83f43`) clears its interval at EOF, so that interval is not stranded, but immediately calls `process.exit(0)`. An isolated Node 24.19.0 paused-reader probe reproduced truncated output for a 1 MiB synthetic request ID: 146,176 bytes arrived and JSON was incomplete despite exit 0. A scratch-only removal of `process.exit(0)` returned all 1,048,924 bytes and exited 0. The 128 KiB control was complete on this Linux host. Adapt #48's natural-drain fix and focused EOF/backpressure regression on the V2 path; inspect other fixture creation paths. This is not a full V2 test pass. | This list classifies the 58 comparison commits under their integration PRs; it is an audit starting point, not a finding that any behavior is already preserved. Inspect additional upstream/V2 changes, instructions and path-specific ownership when resolving each item. @@ -48,3 +48,11 @@ This list classifies the 58 comparison commits under their integration PRs; it i ## Current blockers and evidence This task's local checkout is at `e97641abf69fb88538b53279ded28704b6ccb2b3` and lacks both frozen tip objects. Fetching them over the inherited proxy returned HTTP 503; cloud status reports failed Tailscale enrollment and blocks non-platform network. GitHub connector read-only comparisons and file inspection worked, but no combined tree or tests were produced. The connector's branch summary reports main unprotected and no required checks; rulesets read empty, while direct branch-protection read returned 403 for this integration. Recheck with sufficient visibility before any merge. No claims about Actions, native acceptance or production readiness follow from those reads. + +### Further source inspection and transfer boundary + +The local checkout contains the true merge-base commit `d7819c18813fa03b033cc1c9472c9acc0ffc0618`. The exact main tree `12456a0f25c122faf9f91ba55c3a89a4af85a2d5` was reconstructed from real local `e97641ab` plus the two GitHub-verified #48 blobs using a separate index; it is a verified tree, not a fabricated main commit. GitHub reports held tree `99b04cc52ff8160aaa3403b37ac9faaf8f8f57c7`. The connector supplied recursive metadata for all root subtrees except `.repos`; among those listed, 4,409 distinct held blobs (about 79.3 MB uncompressed) and 487 tree entries are absent locally. `.repos` size and transfer compression are unknown. Individual connector blob transfer is technically possible but thousands of calls and binary content make it inefficient; recursive `.repos` response closed transport. Direct Git fetch already returned 503 and is not being retried unchanged. + +A consumer-local pack of objects reachable from the held tree but not the merge-base tree is the bounded efficient input: `printf '%s\\n' '2f521e6d214512dc573df82c1d143405245439c9^{tree}' '^d7819c18813fa03b033cc1c9472c9acc0ffc0618^{tree}' | git pack-objects --revs --stdout > /tmp/t3-v2-convergence.pack`. Generate only on a source host that already has those exact objects, record the file size and SHA-256, transfer the pack through an authorized local channel, then verify the checksum and Git objects before use. The observed 79.3 MB is an uncompressed lower bound outside `.repos`, not a pack-size estimate. Main and merge-base trees are already local; this pack need not contain commit history. Real merge-parent identities must later come from authentic Git objects or normal GitHub composition, never synthetic commits. + +The EOF probes and exact fixture are retained under `/workspace/scratch/t3-v2-exact/`; they do not alter the held branch. They exercised the fixture directly with synthetic data, not V2 application integration. Full candidate-tree checks, source review and native client qualification remain outstanding. From 0464d4ee5911e0f8db7d2cf8521a56ee10c43ceb Mon Sep 17 00:00:00 2001 From: Kameron Smith <112618179+nullStack65@users.noreply.github.com> Date: Sat, 31 Oct 2026 07:23:28 -0400 Subject: [PATCH 3/3] docs: stage exact V2 preservation patch for review --- .../v2-fork-preservation.draft.patch | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 docs/internals/v2-fork-preservation.draft.patch diff --git a/docs/internals/v2-fork-preservation.draft.patch b/docs/internals/v2-fork-preservation.draft.patch new file mode 100644 index 0000000000000..9c4fe5c5ce21c --- /dev/null +++ b/docs/internals/v2-fork-preservation.draft.patch @@ -0,0 +1,132 @@ +--- a/packages/shared/src/cliRelease.ts ++++ b/packages/shared/src/cliRelease.ts +@@ -5,10 +5,31 @@ + * platform key, so a rename here is a release-breaking change. + */ + +-const CLI_RELEASE_REPOSITORY = "pingdotgg/t3code"; ++/** ++ * The repository this build resolves its own releases from. This is a fork, so ++ * the default must never be upstream: an install that fell back to ++ * `pingdotgg/t3code` would silently update onto an official build and lose the ++ * fork. `T3CODE_RELEASE_REPOSITORY` overrides it for mirrors and tests; unlike ++ * `T3CODE_RELEASE_BASE_URL` it also retargets the release-index lookup that ++ * `t3 update` and the install scripts use to discover a version. ++ */ ++export const CLI_RELEASE_REPOSITORY = "nullStack65/t3code"; ++const CLI_RELEASE_REPOSITORY_ENV = "T3CODE_RELEASE_REPOSITORY"; + export const CLI_RELEASE_CHECKSUMS_FILE = "SHA256SUMS"; + /** Overrides the download origin for mirrors and air-gapped installs. */ + export const CLI_RELEASE_BASE_URL_ENV = "T3CODE_RELEASE_BASE_URL"; ++ ++const REPOSITORY_PATTERN = /^[^/\s]+\/[^/\s]+$/; ++ ++/** The `owner/repo` this build downloads and discovers releases from. */ ++export function resolveCliReleaseRepository( ++ env: Readonly> = process.env, ++): string { ++ const override = env[CLI_RELEASE_REPOSITORY_ENV]?.trim(); ++ return override !== undefined && override !== "" && REPOSITORY_PATTERN.test(override) ++ ? override ++ : CLI_RELEASE_REPOSITORY; ++} + + /** + * The archives a release attaches. Kept in step with the build_linux_cli +@@ -54,14 +75,17 @@ + return `t3-${version}-${platformKey}.${platformKey.startsWith("win32") ? "zip" : "tar.gz"}`; + } + +-const CLI_RELEASE_DEFAULT_BASE_URL = `https://github.com/${CLI_RELEASE_REPOSITORY}/releases/download`; ++const CLI_RELEASE_DEFAULT_BASE_URL = (repository: string) => ++ `https://github.com/${repository}/releases/download`; + + /** Directory that `releases/download//` lives under. */ + export function cliReleaseDownloadBaseUrl( + version: string, +- baseUrl: string | undefined = CLI_RELEASE_DEFAULT_BASE_URL, ++ baseUrl: string | undefined = undefined, ++ repository: string = resolveCliReleaseRepository(), + ): string { +- return `${(baseUrl?.trim() || CLI_RELEASE_DEFAULT_BASE_URL).replace(/\/+$/, "")}/v${version}`; ++ const origin = baseUrl?.trim() || CLI_RELEASE_DEFAULT_BASE_URL(repository); ++ return `${origin.replace(/\/+$/, "")}/v${version}`; + } + + /** +@@ -97,8 +121,11 @@ + * until a channel match turns up; a busy nightly train can push the newest + * preview or stable release past any single page. + */ +-export function cliReleaseIndexPageUrl(page: number): string { +- return `https://api.github.com/repos/${CLI_RELEASE_REPOSITORY}/releases?per_page=100&page=${page}`; ++export function cliReleaseIndexPageUrl( ++ page: number, ++ repository: string = resolveCliReleaseRepository(), ++): string { ++ return `https://api.github.com/repos/${repository}/releases?per_page=100&page=${page}`; + } + + /** +--- a/packages/shared/src/cliRelease.test.ts ++++ b/packages/shared/src/cliRelease.test.ts +@@ -9,6 +9,7 @@ + cliReleaseIndexPageUrl, + newestCliReleaseVersion, + parseChecksums, ++ resolveCliReleaseRepository, + } from "./cliRelease.ts"; + + describe("cliRelease", () => { +@@ -33,10 +34,29 @@ + + it("resolves download URLs under the tagged release, honoring a mirror", () => { + expect(cliReleaseDownloadBaseUrl("1.2.3")).toBe( +- "https://github.com/pingdotgg/t3code/releases/download/v1.2.3", ++ "https://github.com/nullStack65/t3code/releases/download/v1.2.3", + ); + expect(cliReleaseDownloadBaseUrl("1.2.3", "https://mirror.example/t3/")).toBe( + "https://mirror.example/t3/v1.2.3", ++ ); ++ expect(cliReleaseDownloadBaseUrl("1.2.3", undefined, "example-org/fork")).toBe( ++ "https://github.com/example-org/fork/releases/download/v1.2.3", ++ ); ++ }); ++ ++ it("defaults the release repository to the fork and honors an override", () => { ++ // The shipped default must never be upstream, or a fork install would ++ // discover and download official `pingdotgg` builds. ++ expect(resolveCliReleaseRepository({})).toBe("nullStack65/t3code"); ++ expect(resolveCliReleaseRepository({ T3CODE_RELEASE_REPOSITORY: "example-org/fork" })).toBe( ++ "example-org/fork", ++ ); ++ // A blank or malformed override must not silently redirect to nothing. ++ expect(resolveCliReleaseRepository({ T3CODE_RELEASE_REPOSITORY: " " })).toBe( ++ "nullStack65/t3code", ++ ); ++ expect(resolveCliReleaseRepository({ T3CODE_RELEASE_REPOSITORY: "not-a-repo" })).toBe( ++ "nullStack65/t3code", + ); + }); + +@@ -87,8 +107,11 @@ + + it("pages through the release index at the largest page GitHub allows", () => { + expect(cliReleaseIndexPageUrl(1)).toBe( +- "https://api.github.com/repos/pingdotgg/t3code/releases?per_page=100&page=1", ++ "https://api.github.com/repos/nullStack65/t3code/releases?per_page=100&page=1", + ); + expect(cliReleaseIndexPageUrl(3)).toContain("page=3"); ++ expect(cliReleaseIndexPageUrl(2, "example-org/fork")).toBe( ++ "https://api.github.com/repos/example-org/fork/releases?per_page=100&page=2", ++ ); + }); + }); +--- a/apps/server/src/provider/testing/ClaudeCapabilitiesProbe.fixture.mjs ++++ b/apps/server/src/provider/testing/ClaudeCapabilitiesProbe.fixture.mjs +@@ -62,5 +62,4 @@ + const keepAlive = setInterval(() => {}, 1_000); + lines.on("close", () => { + clearInterval(keepAlive); +- process.exit(0); + });