diff --git a/.github/actions/setup-apt-mirrors/action.yml b/.github/actions/setup-apt-mirrors/action.yml index 5beff201d188..e2f292679e59 100644 --- a/.github/actions/setup-apt-mirrors/action.yml +++ b/.github/actions/setup-apt-mirrors/action.yml @@ -5,17 +5,18 @@ runs: steps: - shell: bash run: | - # Replace the existing Blacksmith mirror list as well as direct sources. + # Use a repository-neutral mirror list so this action works on both + # GitHub-hosted and self-hosted Ubuntu runners. printf '%s\tpriority:%s\n' \ https://archive.ubuntu.com/ubuntu 1 \ https://mirrors.edge.kernel.org/ubuntu 2 \ https://mirror.math.princeton.edu/pub/ubuntu 3 \ - | sudo tee /etc/apt/blacksmith-ubuntu-mirrors.txt > /dev/null + | sudo tee /etc/apt/t3-ubuntu-mirrors.txt > /dev/null # APT's mirror transport retries each file against the next server. sudo find /etc/apt -maxdepth 2 -type f \( -name '*.list' -o -name '*.sources' \) \ -exec sed -i -E \ - 's#https?://(([^/]+\.)?archive|security)\.ubuntu\.com/ubuntu/?#mirror+file:/etc/apt/blacksmith-ubuntu-mirrors.txt#g' {} + + 's#https?://(([^/]+\.)?archive|security)\.ubuntu\.com/ubuntu/?#mirror+file:/etc/apt/t3-ubuntu-mirrors.txt#g' {} + # Move on to a fallback before an unreachable server exhausts the job. printf '%s\n' 'Acquire::http::Timeout "15";' 'Acquire::https::Timeout "15";' \ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f65c15696d2c..9722ebcf89a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ concurrency: jobs: check: name: Check - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: Checkout @@ -62,7 +62,7 @@ jobs: - name: Install browser secret helper build libraries run: | - sudo sed -i 's|http://|https://|g' /etc/apt/blacksmith-ubuntu-mirrors.txt /etc/apt/sources.list.d/ubuntu.sources + sudo sed -i 's|http://|https://|g' /etc/apt/t3-ubuntu-mirrors.txt /etc/apt/sources.list.d/ubuntu.sources sudo apt-get update && sudo apt-get install -y libsecret-1-dev pkg-config - name: Build desktop pipeline @@ -78,7 +78,7 @@ jobs: # limit stays at the default 4 so peak load per runner is unchanged. test: name: Test - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: Checkout @@ -103,7 +103,7 @@ jobs: - name: Install browser secret helper build libraries run: | - sudo sed -i 's|http://|https://|g' /etc/apt/blacksmith-ubuntu-mirrors.txt /etc/apt/sources.list.d/ubuntu.sources + sudo sed -i 's|http://|https://|g' /etc/apt/t3-ubuntu-mirrors.txt /etc/apt/sources.list.d/ubuntu.sources sudo apt-get update && sudo apt-get install -y libsecret-1-dev pkg-config - name: Test preview artifact validation @@ -121,7 +121,7 @@ jobs: # isolation that flag buys is preserved exactly. test_server: name: Test Server ${{ matrix.shard }} - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 10 strategy: fail-fast: false @@ -188,7 +188,7 @@ jobs: # for checks that take under 3s, on the critical path of every PR. rust: name: Rust - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: Checkout @@ -222,7 +222,7 @@ jobs: # the diff cannot be resolved, the lint runs. mobile_native_changes: name: Mobile Native Changes - runs-on: blacksmith-2vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 5 permissions: contents: read @@ -300,7 +300,7 @@ jobs: # Skip only on an explicit "no": a gate job that failed or errored leaves the # output empty, and that must run the lint rather than silently skip it. if: ${{ !cancelled() && needs.mobile_native_changes.outputs.changed != 'false' }} - runs-on: blacksmith-6vcpu-macos-26 + runs-on: macos-14 timeout-minutes: 10 steps: - name: Checkout @@ -328,7 +328,7 @@ jobs: release_smoke: name: Release Smoke - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: Checkout diff --git a/.github/workflows/mobile-fingerprint-check.yml b/.github/workflows/mobile-fingerprint-check.yml index b8b872f019f6..5849b71ddbb8 100644 --- a/.github/workflows/mobile-fingerprint-check.yml +++ b/.github/workflows/mobile-fingerprint-check.yml @@ -24,7 +24,7 @@ concurrency: jobs: fingerprint: name: Native fingerprint diff - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 permissions: contents: read issues: write diff --git a/apps/server/src/usage/routeMetadata.ts b/apps/server/src/usage/routeMetadata.ts index 410742ef8739..b55b1d982007 100644 --- a/apps/server/src/usage/routeMetadata.ts +++ b/apps/server/src/usage/routeMetadata.ts @@ -16,7 +16,7 @@ */ /** Why a route event happened. `null` means "request only, not classified". */ -export const ROUTE_EVENT_KINDS = [ +const ROUTE_EVENT_KINDS = [ "normal", "availability_fallback", "canary", @@ -29,7 +29,7 @@ export type RouteEventKind = (typeof ROUTE_EVENT_KINDS)[number]; * A bounded, coarse task class known *before* execution. `unknown` is a first * class value: the caller must be able to abstain rather than guess. */ -export const TASK_STRATA = [ +const TASK_STRATA = [ "investigation", "docs", "tests", @@ -50,7 +50,7 @@ export function isRouteEventKind(value: unknown): value is RouteEventKind { return typeof value === "string" && ROUTE_EVENT_KIND_SET.has(value); } -export function isTaskStratum(value: unknown): value is TaskStratum { +function isTaskStratum(value: unknown): value is TaskStratum { return typeof value === "string" && TASK_STRATUM_SET.has(value); } @@ -92,7 +92,7 @@ export function normalizeProviderInstanceKey(value: unknown): string { * normalizes to `null` rather than being stored, so arbitrary prose cannot * leak into the metadata carrier. */ -export const MAX_ESCALATION_REASON_LENGTH = 64; +const MAX_ESCALATION_REASON_LENGTH = 64; const ESCALATION_REASON_PATTERN = /^[a-z0-9][a-z0-9_.:-]*$/; export function normalizeEscalationReason(value: unknown): string | null { diff --git a/apps/server/src/usage/usageAttribution.ts b/apps/server/src/usage/usageAttribution.ts index 850172204c63..bbac8f684918 100644 --- a/apps/server/src/usage/usageAttribution.ts +++ b/apps/server/src/usage/usageAttribution.ts @@ -100,7 +100,7 @@ export interface AttributionSourceCapability { readonly note: string; } -export const ATTRIBUTION_SOURCE_CAPABILITIES: readonly AttributionSourceCapability[] = [ +const ATTRIBUTION_SOURCE_CAPABILITIES: readonly AttributionSourceCapability[] = [ { provider: "claude", nativeSource: "transcript", diff --git a/apps/server/src/usage/usageRouteAttribution.ts b/apps/server/src/usage/usageRouteAttribution.ts index a435de73a273..d913c46b16e3 100644 --- a/apps/server/src/usage/usageRouteAttribution.ts +++ b/apps/server/src/usage/usageRouteAttribution.ts @@ -48,7 +48,7 @@ import { } from "./routeMetadata.ts"; import { addTotals, EMPTY_TOTALS } from "./usageTranscripts.ts"; -export const USAGE_ROUTE_ATTRIBUTION_VERSION = 1 as const; +const USAGE_ROUTE_ATTRIBUTION_VERSION = 1 as const; export interface UsageRouteAttributionInput { /** Read cutoff; associations are as of this instant. */ diff --git a/knip.jsonc b/knip.jsonc index 5e87b4d5bc55..6cd759237a4f 100644 --- a/knip.jsonc +++ b/knip.jsonc @@ -14,7 +14,16 @@ }, "scripts": { // Knip loads its preprocessor through a CLI option; native verification runs directly. - "entry": ["knip-schemas.ts", "mobile-native-client.ts"], + // These are documented operator entrypoints for fork candidate build, + // promotion, and artifact staging; they are intentionally invoked by + // release operators/workflows rather than imported by workspace code. + "entry": [ + "knip-schemas.ts", + "mobile-native-client.ts", + "build-fork-candidate.ts", + "promote-fork-candidate.ts", + "stage-candidate-asset.ts", + ], }, "apps/server": { // Vite+ pack entries and the launcher used by installed background services. diff --git a/packages/shared/src/cliRelease.ts b/packages/shared/src/cliRelease.ts index a3d19698558e..77e421b64983 100644 --- a/packages/shared/src/cliRelease.ts +++ b/packages/shared/src/cliRelease.ts @@ -14,7 +14,7 @@ * `t3 update` and the install scripts use to discover a version. */ export const CLI_RELEASE_REPOSITORY = "nullStack65/t3code"; -export const CLI_RELEASE_REPOSITORY_ENV = "T3CODE_RELEASE_REPOSITORY"; +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"; diff --git a/scripts/build-desktop-artifact.ts b/scripts/build-desktop-artifact.ts index f8e71c84993a..8a3d2751b727 100644 --- a/scripts/build-desktop-artifact.ts +++ b/scripts/build-desktop-artifact.ts @@ -44,6 +44,10 @@ import { resolveSourceRepository, serializeBuildInfo, } from "./lib/source-provenance.ts"; +import { + WSL_RUNTIME_ARCHIVE_HASH_NAME, + WSL_RUNTIME_ARCHIVE_NAME, +} from "./lib/wsl-runtime-artifact.ts"; import * as NodeRuntime from "@effect/platform-node/NodeRuntime"; import * as NodeServices from "@effect/platform-node/NodeServices"; @@ -1034,8 +1038,10 @@ export const WINDOWS_SERVER_EXTRA_RESOURCES = [ filter: [WINDOWS_SERVER_ASAR_RESOURCE, `${WINDOWS_SERVER_ASAR_RESOURCE}.unpacked/**/*`], }, ] as const; -export const WSL_RUNTIME_ARCHIVE_NAME = "wsl-runtime.tar.gz"; -export const WSL_RUNTIME_ARCHIVE_HASH_NAME = `${WSL_RUNTIME_ARCHIVE_NAME}.sha256`; +export { + WSL_RUNTIME_ARCHIVE_HASH_NAME, + WSL_RUNTIME_ARCHIVE_NAME, +} from "./lib/wsl-runtime-artifact.ts"; export const WSL_RUNTIME_ARCHIVE_EXTRA_RESOURCE = { from: `apps/desktop/prod-resources/${WSL_RUNTIME_ARCHIVE_NAME}`, to: WSL_RUNTIME_ARCHIVE_NAME, diff --git a/scripts/lib/candidate-provenance-inspect.ts b/scripts/lib/candidate-provenance-inspect.ts index f1cc34e16f29..89e8f32464c8 100644 --- a/scripts/lib/candidate-provenance-inspect.ts +++ b/scripts/lib/candidate-provenance-inspect.ts @@ -32,10 +32,7 @@ import * as NodePath from "node:path"; import { extractFile } from "@electron/asar"; import { BUILD_INFO_FILE_NAME, parseBuildInfo } from "./source-provenance.ts"; -import { - WSL_RUNTIME_ARCHIVE_NAME, - WSL_RUNTIME_ARCHIVE_HASH_NAME, -} from "../build-desktop-artifact.ts"; +import { WSL_RUNTIME_ARCHIVE_NAME, WSL_RUNTIME_ARCHIVE_HASH_NAME } from "./wsl-runtime-artifact.ts"; import { sha256Hex, type BundledServerRecord, diff --git a/scripts/lib/wsl-runtime-artifact.ts b/scripts/lib/wsl-runtime-artifact.ts new file mode 100644 index 000000000000..9a841debc538 --- /dev/null +++ b/scripts/lib/wsl-runtime-artifact.ts @@ -0,0 +1,8 @@ +/** + * Names of the WSL runtime archive and its digest sidecar embedded in desktop + * resources. Keep these in the shared scripts/lib surface so build and + * provenance inspection tools can use the same contract without importing the + * full desktop build command graph. + */ +export const WSL_RUNTIME_ARCHIVE_NAME = "wsl-runtime.tar.gz"; +export const WSL_RUNTIME_ARCHIVE_HASH_NAME = `${WSL_RUNTIME_ARCHIVE_NAME}.sha256`; diff --git a/scripts/verify-windows-installer.ts b/scripts/verify-windows-installer.ts index 0cd688711374..e8e6df0b60d8 100644 --- a/scripts/verify-windows-installer.ts +++ b/scripts/verify-windows-installer.ts @@ -23,7 +23,7 @@ import * as NodePath from "node:path"; import { parseBuildInfo } from "./lib/source-provenance.ts"; import { verifyEmbeddedWslRuntime, type EmbeddedBuildInfo } from "./lib/wsl-payload.ts"; -import { WSL_RUNTIME_ARCHIVE_NAME } from "./build-desktop-artifact.ts"; +import { WSL_RUNTIME_ARCHIVE_NAME } from "./lib/wsl-runtime-artifact.ts"; interface Args { installer: string;