diff --git a/apps/server/src/bin.ts b/apps/server/src/bin.ts index 0997c7a250..7661843ea9 100644 --- a/apps/server/src/bin.ts +++ b/apps/server/src/bin.ts @@ -17,7 +17,7 @@ const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, NetService.layer); const makeCli = () => Command.make("mate", { ...sharedServerCommandFlags }).pipe( - Command.withDescription("Run the T3 Code server."), + Command.withDescription("Run the Zerops Mate server."), Command.withHandler((flags) => runServerCommand(flags)), Command.withSubcommands([ startCommand, diff --git a/apps/server/src/cli/config.ts b/apps/server/src/cli/config.ts index 0b5972c519..8af0f8401f 100644 --- a/apps/server/src/cli/config.ts +++ b/apps/server/src/cli/config.ts @@ -40,7 +40,7 @@ export const hostFlag = Flag.String("host").pipe( ); export const baseDirFlag = Flag.String("base-dir").pipe( Flag.withDescription( - "Explicit T3 Code data directory; runtime state is stored under userdata (equivalent to T3CODE_HOME).", + "Explicit Zerops Mate data directory; runtime state is stored under userdata (equivalent to T3CODE_HOME).", ), Flag.optional, ); diff --git a/apps/server/src/cli/server.ts b/apps/server/src/cli/server.ts index bc4b3f4570..bfca6a63b3 100644 --- a/apps/server/src/cli/server.ts +++ b/apps/server/src/cli/server.ts @@ -19,13 +19,13 @@ export const runServerCommand = ( }); export const startCommand = Command.make("start", { ...sharedServerCommandFlags }).pipe( - Command.withDescription("Run the T3 Code server."), + Command.withDescription("Run the Zerops Mate server."), Command.withHandler((flags) => runServerCommand(flags)), ); export const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe( Command.withDescription( - "Run the T3 Code server without opening a browser and print headless pairing details.", + "Run the Zerops Mate server without opening a browser and print headless pairing details.", ), Command.withHandler((flags) => runServerCommand(flags, { diff --git a/apps/server/src/cli/triage.ts b/apps/server/src/cli/triage.ts index f5dd521699..5c04f5ea74 100644 --- a/apps/server/src/cli/triage.ts +++ b/apps/server/src/cli/triage.ts @@ -169,7 +169,7 @@ export const triageCommand = Command.make("triage", { model: modelFlag, }).pipe( Command.withDescription( - "Investigate a T3 Code problem on this machine with claude or codex, and help file a good issue.", + "Investigate a Zerops Mate problem on this machine with claude or codex, and help file a good issue.", ), Command.withHandler((flags) => Effect.gen(function* () { diff --git a/apps/server/src/cloud/cliAuthHtml.ts b/apps/server/src/cloud/cliAuthHtml.ts index 69d3b471ae..236daf90c9 100644 --- a/apps/server/src/cloud/cliAuthHtml.ts +++ b/apps/server/src/cloud/cliAuthHtml.ts @@ -7,9 +7,9 @@ function resolveLoopbackAuthorizationStage(): LoopbackAuthorizationStage { } const stageBrands = { - dev: "T3 Code (Dev)", - nightly: "T3 Code (Nightly)", - latest: "T3 Code", + dev: "Zerops Mate (Dev)", + nightly: "Zerops Mate (Nightly)", + latest: "Zerops Mate", } as const satisfies Record; export function renderLoopbackAuthorizationCompleteHtml( diff --git a/apps/server/src/provider/CodexDeveloperInstructions.ts b/apps/server/src/provider/CodexDeveloperInstructions.ts index 37ec4d133d..579783c2f3 100644 --- a/apps/server/src/provider/CodexDeveloperInstructions.ts +++ b/apps/server/src/provider/CodexDeveloperInstructions.ts @@ -159,7 +159,7 @@ export function buildCodexDeveloperInstructions(interactionMode: ProviderInterac } /** - * T3 Code context for `turn/start.additionalContext`. Codex renders each entry + * Mate's context for `turn/start.additionalContext`. Codex renders each entry * as a `value` developer message and resends it only when the value * changes. * @@ -171,7 +171,7 @@ export function buildCodexAdditionalContext( runtime: CodexRuntimeInfo, ): Record { return { - t3_code_runtime: { + mate_runtime: { kind: "application", value: buildRuntimeInstructions({ harness: "Codex", ...runtime }), }, diff --git a/apps/server/src/provider/Layers/AntigravityProvider.ts b/apps/server/src/provider/Layers/AntigravityProvider.ts index 956a5d81d3..6534609f10 100644 --- a/apps/server/src/provider/Layers/AntigravityProvider.ts +++ b/apps/server/src/provider/Layers/AntigravityProvider.ts @@ -149,7 +149,7 @@ export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(func auth: { status: "unknown", ...(options.auth ? { type: options.auth.type } : {}) }, message: settings.enabled ? "Checking Antigravity availability." - : "Antigravity is disabled in T3 Code settings.", + : "Antigravity is disabled in settings.", }, }), setup: { canAuthenticate: true, canInstall: true }, diff --git a/apps/server/src/provider/Layers/ClaudeAdapter.test.ts b/apps/server/src/provider/Layers/ClaudeAdapter.test.ts index 778b637f96..d84e8803f9 100644 --- a/apps/server/src/provider/Layers/ClaudeAdapter.test.ts +++ b/apps/server/src/provider/Layers/ClaudeAdapter.test.ts @@ -469,7 +469,7 @@ describe("ClaudeAdapterLive", () => { type: "preset", preset: "claude_code", append: - "In case you're asked: you are running in T3 Code through the Claude Code harness. No need to mention this otherwise. You can embed images and videos in your response using Markdown with absolute file paths.", + "In case you're asked: you are running in Zerops Mate through the Claude Code harness. No need to mention this otherwise. You can embed images and videos in your response using Markdown with absolute file paths.", }); assert.equal(createInput?.options.permissionMode, "bypassPermissions"); assert.equal(createInput?.options.allowDangerouslySkipPermissions, true); diff --git a/apps/server/src/provider/Layers/ClaudeProvider.ts b/apps/server/src/provider/Layers/ClaudeProvider.ts index db06557c7c..ad22419e9b 100644 --- a/apps/server/src/provider/Layers/ClaudeProvider.ts +++ b/apps/server/src/provider/Layers/ClaudeProvider.ts @@ -453,7 +453,7 @@ export const checkClaudeProviderStatus = Effect.fn("checkClaudeProviderStatus")( version: null, status: "warning", auth: { status: "unknown" }, - message: "Claude is disabled in T3 Code settings.", + message: "Claude is disabled in settings.", }, }); } @@ -625,7 +625,7 @@ export const makePendingClaudeProvider = ( version: null, status: "warning", auth: { status: "unknown" }, - message: "Claude is disabled in T3 Code settings.", + message: "Claude is disabled in settings.", }, }); } diff --git a/apps/server/src/provider/Layers/CodexCollabRuntime.integration.test.ts b/apps/server/src/provider/Layers/CodexCollabRuntime.integration.test.ts index 5405169926..b9f92a8d5d 100644 --- a/apps/server/src/provider/Layers/CodexCollabRuntime.integration.test.ts +++ b/apps/server/src/provider/Layers/CodexCollabRuntime.integration.test.ts @@ -934,7 +934,7 @@ describe("CodexSessionRuntime compaction", () => { assert.lengthOf(texts, 1); assert.match( texts[0] ?? "", - /^.*as GPT-5\.6 Sol \(model slug: gpt-5\.6-sol\).*<\/t3_code_runtime>$/s, + /^.*as GPT-5\.6 Sol \(model slug: gpt-5\.6-sol\).*<\/mate_runtime>$/s, ); yield* runtime.close; diff --git a/apps/server/src/provider/Layers/CodexProvider.ts b/apps/server/src/provider/Layers/CodexProvider.ts index d99b97150c..5cf4eb366c 100644 --- a/apps/server/src/provider/Layers/CodexProvider.ts +++ b/apps/server/src/provider/Layers/CodexProvider.ts @@ -344,7 +344,7 @@ export function buildCodexInitializeParams(): CodexSchema.V1InitializeParams { return { clientInfo: { name: "t3code_desktop", - title: "T3 Code Desktop", + title: "Zerops Mate", version: packageJson.version, }, capabilities: { @@ -508,7 +508,7 @@ const makePendingCodexProvider = ( version: null, status: "warning", auth: { status: "unknown" }, - message: "Codex is disabled in T3 Code settings.", + message: "Codex is disabled in settings.", }, }); } @@ -594,7 +594,7 @@ export const checkCodexProviderStatus = Effect.fn("checkCodexProviderStatus")(fu version: null, status: "warning", auth: { status: "unknown" }, - message: "Codex is disabled in T3 Code settings.", + message: "Codex is disabled in settings.", }, }); } diff --git a/apps/server/src/provider/Layers/CodexSessionRuntime.test.ts b/apps/server/src/provider/Layers/CodexSessionRuntime.test.ts index 89ec6d741e..34c30c28c4 100644 --- a/apps/server/src/provider/Layers/CodexSessionRuntime.test.ts +++ b/apps/server/src/provider/Layers/CodexSessionRuntime.test.ts @@ -308,7 +308,7 @@ describe("buildTurnStartParams", () => { NodeAssert.equal(settings?.model, DEFAULT_MODEL); NodeAssert.equal(settings?.reasoning_effort, "medium"); NodeAssert.ok( - params.additionalContext?.t3_code_runtime?.value.includes(`as ${DEFAULT_MODEL} with medium`), + params.additionalContext?.mate_runtime?.value.includes(`as ${DEFAULT_MODEL} with medium`), ); }); @@ -324,7 +324,7 @@ describe("buildTurnStartParams", () => { }); NodeAssert.match( - params.additionalContext?.t3_code_runtime?.value ?? "", + params.additionalContext?.mate_runtime?.value ?? "", /as GPT-5\.3-Codex \(model slug: gpt-5\.3-codex\) with high reasoning effort/, ); }), @@ -596,12 +596,12 @@ describe("buildCodexDeveloperInstructions", () => { describe("buildCodexAdditionalContext", () => { const runtime = { model: "gpt-5.3-codex", reasoningEffort: "high" }; const runtimeValue = (context: ReturnType) => - context.t3_code_runtime?.value ?? ""; + context.mate_runtime?.value ?? ""; it("describes the harness, model, effort, and Markdown media support", () => { const context = buildCodexAdditionalContext(runtime); - NodeAssert.equal(context.t3_code_runtime?.kind, "application"); + NodeAssert.equal(context.mate_runtime?.kind, "application"); NodeAssert.match( runtimeValue(context), /.*Codex harness, as gpt-5\.3-codex with high reasoning effort.*embed images and videos.*Markdown.*<\/runtime_info>/, @@ -639,7 +639,7 @@ describe("Codex developer instructions never mention preview tools", () => { it("Codex developer instructions never mention preview tools", () => { const runtime = { model: "gpt-5.3-codex", reasoningEffort: "medium" }; const context = buildCodexAdditionalContext(runtime); - NodeAssert.deepStrictEqual(Object.keys(context), ["t3_code_runtime"]); + NodeAssert.deepStrictEqual(Object.keys(context), ["mate_runtime"]); for (const instructions of [ buildCodexDeveloperInstructions("default"), buildCodexDeveloperInstructions("plan"), diff --git a/apps/server/src/provider/Layers/CursorProvider.test.ts b/apps/server/src/provider/Layers/CursorProvider.test.ts index 5e2970a6e5..d9fbb3c376 100644 --- a/apps/server/src/provider/Layers/CursorProvider.test.ts +++ b/apps/server/src/provider/Layers/CursorProvider.test.ts @@ -309,14 +309,14 @@ const baseCursorSettings: CursorSettings = { }; const cursorAcpDiscoveryFailedMessage = [ "Cursor ACP model discovery failed.", - "Cursor CLI setup may be incomplete; install or enable the Cursor CLI, restart T3 Code, and try again.", + "Cursor CLI setup may be incomplete; install or enable the Cursor CLI, restart Zerops Mate, and try again.", "See https://cursor.com/docs/cli/installation.", "Check server logs for ACP details.", ].join(" "); const missingCursorBinaryPath = "/definitely/not/installed/t3-cursor-agent"; const cursorCliCommandMissingMessage = [ `Cursor CLI command \`${missingCursorBinaryPath}\` was not found.`, - `Install or enable the Cursor CLI, make sure \`${missingCursorBinaryPath}\` is on PATH, then restart T3 Code.`, + `Install or enable the Cursor CLI, make sure \`${missingCursorBinaryPath}\` is on PATH, then restart Zerops Mate.`, "See https://cursor.com/docs/cli/installation.", ].join(" "); diff --git a/apps/server/src/provider/Layers/CursorProvider.ts b/apps/server/src/provider/Layers/CursorProvider.ts index dfaa8ffe33..a714102b95 100644 --- a/apps/server/src/provider/Layers/CursorProvider.ts +++ b/apps/server/src/provider/Layers/CursorProvider.ts @@ -158,7 +158,7 @@ const CURSOR_PARAMETERIZED_MODEL_PICKER_MIN_VERSION_DATE = 2026_04_08; const CURSOR_CLI_INSTALLATION_DOCS_URL = "https://cursor.com/docs/cli/installation"; const CURSOR_ACP_MODEL_DISCOVERY_FAILED_MESSAGE = [ "Cursor ACP model discovery failed.", - "Cursor CLI setup may be incomplete; install or enable the Cursor CLI, restart T3 Code, and try again.", + "Cursor CLI setup may be incomplete; install or enable the Cursor CLI, restart Zerops Mate, and try again.", `See ${CURSOR_CLI_INSTALLATION_DOCS_URL}.`, "Check server logs for ACP details.", ].join(" "); @@ -186,7 +186,7 @@ export function buildInitialCursorProviderSnapshot( version: null, status: "warning", auth: { status: "unknown" }, - message: "Cursor is disabled in T3 Code settings.", + message: "Cursor is disabled in settings.", }, }); } @@ -731,7 +731,7 @@ function joinProviderMessages(...messages: ReadonlyArray): s function buildCursorCliCommandMissingMessage(binaryPath: string): string { return [ `Cursor CLI command \`${binaryPath}\` was not found.`, - `Install or enable the Cursor CLI, make sure \`${binaryPath}\` is on PATH, then restart T3 Code.`, + `Install or enable the Cursor CLI, make sure \`${binaryPath}\` is on PATH, then restart Zerops Mate.`, `See ${CURSOR_CLI_INSTALLATION_DOCS_URL}.`, ].join(" "); } @@ -1122,7 +1122,7 @@ export const checkCursorProviderStatus = Effect.fn("checkCursorProviderStatus")( version: null, status: "warning", auth: { status: "unknown" }, - message: "Cursor is disabled in T3 Code settings.", + message: "Cursor is disabled in settings.", }, }); } diff --git a/apps/server/src/provider/Layers/GrokProvider.ts b/apps/server/src/provider/Layers/GrokProvider.ts index 61cd8a9a38..2c59eb288f 100644 --- a/apps/server/src/provider/Layers/GrokProvider.ts +++ b/apps/server/src/provider/Layers/GrokProvider.ts @@ -86,7 +86,7 @@ export function buildInitialGrokProviderSnapshot( version: null, status: "warning", auth: { status: "unknown" }, - message: "Grok is disabled in T3 Code settings.", + message: "Grok is disabled in settings.", }, }); } @@ -386,7 +386,7 @@ export const checkGrokProviderStatus = Effect.fn("checkGrokProviderStatus")(func version: null, status: "warning", auth: { status: "unknown" }, - message: "Grok is disabled in T3 Code settings.", + message: "Grok is disabled in settings.", }, }); } diff --git a/apps/server/src/provider/Layers/OpenCodeAdapter.ts b/apps/server/src/provider/Layers/OpenCodeAdapter.ts index 52dab4f500..553f723f89 100644 --- a/apps/server/src/provider/Layers/OpenCodeAdapter.ts +++ b/apps/server/src/provider/Layers/OpenCodeAdapter.ts @@ -1207,7 +1207,7 @@ export function makeOpenCodeAdapter( return; } const detail = - "OpenCode accepted the prompt, but T3 Code could not confirm its message or session status."; + "OpenCode accepted the prompt, but Zerops Mate could not confirm its message or session status."; const abortExit = yield* Effect.exit( runOpenCodeSdk("session.abort", (signal) => context.client.session.abort({ sessionID: context.openCodeSessionId }, { signal }), diff --git a/apps/server/src/provider/Layers/OpenCodeProvider.ts b/apps/server/src/provider/Layers/OpenCodeProvider.ts index 0495f8b307..2c3bfe2ea2 100644 --- a/apps/server/src/provider/Layers/OpenCodeProvider.ts +++ b/apps/server/src/provider/Layers/OpenCodeProvider.ts @@ -360,8 +360,8 @@ export const makePendingOpenCodeProvider = ( auth: { status: "unknown" }, message: openCodeSettings.serverUrl.trim().length > 0 - ? "OpenCode is disabled in T3 Code settings. A server URL is configured." - : "OpenCode is disabled in T3 Code settings.", + ? "OpenCode is disabled in settings. A server URL is configured." + : "OpenCode is disabled in settings.", }, }); } @@ -435,8 +435,8 @@ export const checkOpenCodeProviderStatus = Effect.fn("checkOpenCodeProviderStatu status: "warning", auth: { status: "unknown" }, message: isExternalServer - ? "OpenCode is disabled in T3 Code settings. A server URL is configured." - : "OpenCode is disabled in T3 Code settings.", + ? "OpenCode is disabled in settings. A server URL is configured." + : "OpenCode is disabled in settings.", }, }); } @@ -473,7 +473,7 @@ export const checkOpenCodeProviderStatus = Effect.fn("checkOpenCodeProviderStatu if (!version) { return fallback( new Error( - `Unable to determine OpenCode version from \`opencode --version\` output. T3 Code requires OpenCode v${MINIMUM_OPENCODE_VERSION} or newer.`, + `Unable to determine OpenCode version from \`opencode --version\` output. Zerops Mate requires OpenCode v${MINIMUM_OPENCODE_VERSION} or newer.`, ), null, ); diff --git a/apps/server/src/provider/Layers/ProviderAuthService.ts b/apps/server/src/provider/Layers/ProviderAuthService.ts index cec2a58788..114e83ba14 100644 --- a/apps/server/src/provider/Layers/ProviderAuthService.ts +++ b/apps/server/src/provider/Layers/ProviderAuthService.ts @@ -25,7 +25,7 @@ export const makeProviderAuthService = Effect.gen(function* () { instanceId, operation, detail: instance - ? "This provider does not support sign-in in T3 Code." + ? "This provider does not support sign-in in Zerops Mate." : "This provider instance is no longer available.", }); } diff --git a/apps/server/src/provider/Layers/ProviderRegistry.test.ts b/apps/server/src/provider/Layers/ProviderRegistry.test.ts index ee1a235732..7a3ac7dfb1 100644 --- a/apps/server/src/provider/Layers/ProviderRegistry.test.ts +++ b/apps/server/src/provider/Layers/ProviderRegistry.test.ts @@ -2649,10 +2649,7 @@ it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te ]); assert.strictEqual(cursorProvider?.enabled, false); assert.strictEqual(cursorProvider?.status, "disabled"); - assert.strictEqual( - cursorProvider?.message, - "Cursor is disabled in T3 Code settings.", - ); + assert.strictEqual(cursorProvider?.message, "Cursor is disabled in settings."); assert.strictEqual(cursorSpawned, false); }).pipe(Effect.provide(runtimeServices)); }), @@ -2666,7 +2663,7 @@ it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te assert.strictEqual(status.enabled, false); assert.strictEqual(status.status, "disabled"); assert.strictEqual(status.installed, false); - assert.strictEqual(status.message, "Codex is disabled in T3 Code settings."); + assert.strictEqual(status.message, "Codex is disabled in settings."); }), ); }); diff --git a/apps/server/src/provider/Layers/ProviderService.ts b/apps/server/src/provider/Layers/ProviderService.ts index fb721cf860..0701a624e9 100644 --- a/apps/server/src/provider/Layers/ProviderService.ts +++ b/apps/server/src/provider/Layers/ProviderService.ts @@ -705,7 +705,7 @@ const makeProviderService = Effect.fn("makeProviderService")(function* ( if (!instanceInfo.enabled) { return yield* toValidationError( "ProviderService.startSession", - `Provider instance '${resolvedInstanceId}' is disabled in T3 Code settings.`, + `Provider instance '${resolvedInstanceId}' is disabled in settings.`, ); } const persistedBinding = Option.getOrUndefined(yield* directory.getBinding(threadId)); diff --git a/apps/server/src/provider/RuntimeInstructions.ts b/apps/server/src/provider/RuntimeInstructions.ts index 1ce4f81687..1e671fbe9a 100644 --- a/apps/server/src/provider/RuntimeInstructions.ts +++ b/apps/server/src/provider/RuntimeInstructions.ts @@ -16,7 +16,7 @@ export function buildRuntimeInstructions(runtime: { modelName && modelName !== model ? `${modelName} (model slug: ${model})` : model; const modelInfo = model && model !== "auto" && model !== "default" ? `, as ${modelLabel}` : ""; const effortInfo = effort ? ` with ${effort} reasoning effort` : ""; - return `In case you're asked: you are running in T3 Code through the ${harness} harness${modelInfo}${effortInfo}. No need to mention this otherwise. You can embed images and videos in your response using Markdown with absolute file paths.`; + return `In case you're asked: you are running in Zerops Mate through the ${harness} harness${modelInfo}${effortInfo}. No need to mention this otherwise. You can embed images and videos in your response using Markdown with absolute file paths.`; } function toSingleLine(value: string): string { diff --git a/apps/server/src/provider/opencodeRuntime.ts b/apps/server/src/provider/opencodeRuntime.ts index e87f758e0e..090af67e59 100644 --- a/apps/server/src/provider/opencodeRuntime.ts +++ b/apps/server/src/provider/opencodeRuntime.ts @@ -158,7 +158,7 @@ export const verifyOpenCodeServerVersion = Effect.fn("verifyOpenCodeServerVersio (cause) => new OpenCodeRuntimeError({ operation: "global.health", - detail: `OpenCode server returned an invalid health response. T3 Code requires OpenCode v${MINIMUM_OPENCODE_VERSION} or newer.`, + detail: `OpenCode server returned an invalid health response. Zerops Mate requires OpenCode v${MINIMUM_OPENCODE_VERSION} or newer.`, cause, }), ), @@ -166,7 +166,7 @@ export const verifyOpenCodeServerVersion = Effect.fn("verifyOpenCodeServerVersio if (parseSemver(health.version) === null) { return yield* new OpenCodeRuntimeError({ operation: "global.health", - detail: `OpenCode server returned an invalid version. T3 Code requires OpenCode v${MINIMUM_OPENCODE_VERSION} or newer.`, + detail: `OpenCode server returned an invalid version. Zerops Mate requires OpenCode v${MINIMUM_OPENCODE_VERSION} or newer.`, }); } if (compareSemverVersions(health.version, MINIMUM_OPENCODE_VERSION) < 0) { diff --git a/apps/server/src/provider/providerCompatibility.ts b/apps/server/src/provider/providerCompatibility.ts index b4ce66f876..0011727163 100644 --- a/apps/server/src/provider/providerCompatibility.ts +++ b/apps/server/src/provider/providerCompatibility.ts @@ -82,11 +82,11 @@ export function resolveProviderCompatibility( : "unknown"; const message = status === "broken" - ? "This provider version is known to be incompatible with this T3 Code release." + ? "This provider version is known to be incompatible with this Zerops Mate release." : status === "unsupported" - ? "This provider version is outside the supported range for this T3 Code release." + ? "This provider version is outside the supported range for this Zerops Mate release." : status === "graceful" - ? "This provider version has limited compatibility with this T3 Code release." + ? "This provider version has limited compatibility with this Zerops Mate release." : null; const recommendedVersion = policy.recommendedVersion ?? null; const recommendedRange = policy.recommendedRange ?? null; diff --git a/apps/server/src/provider/providerInstallation.ts b/apps/server/src/provider/providerInstallation.ts index 42c5c3b547..f44ad12ec1 100644 --- a/apps/server/src/provider/providerInstallation.ts +++ b/apps/server/src/provider/providerInstallation.ts @@ -79,7 +79,7 @@ export const makeProviderInstallation = Effect.fn("makeProviderInstallation")(fu instanceId, operation, detail: - "This instance uses a custom executable. Clear its binary path to manage installation in T3 Code.", + "This instance uses a custom executable. Clear its binary path to manage installation in Zerops Mate.", }); } }); diff --git a/apps/server/src/provider/providerMaintenanceRunner.ts b/apps/server/src/provider/providerMaintenanceRunner.ts index 17be8eb087..6c816a0079 100644 --- a/apps/server/src/provider/providerMaintenanceRunner.ts +++ b/apps/server/src/provider/providerMaintenanceRunner.ts @@ -416,7 +416,7 @@ export const make = Effect.fn("ProviderMaintenanceRunner.make")(function* () { message: targetVersion !== undefined ? "This version is no longer recommended or this installer cannot install a specific version. Refresh provider settings." - : "The latest provider version is incompatible with this T3 Code release. Review provider settings.", + : "The latest provider version is incompatible with this Zerops Mate release. Review provider settings.", }), ); } @@ -466,9 +466,9 @@ export const make = Effect.fn("ProviderMaintenanceRunner.make")(function* () { startedAt, finishedAt, message: couldNotVerify - ? "Update command completed, but T3 Code could not verify the provider version." + ? "Update command completed, but Zerops Mate could not verify the provider version." : stillOutdated - ? "Update command completed, but T3 Code still detects an outdated provider version." + ? "Update command completed, but Zerops Mate still detects an outdated provider version." : "Provider updated.", output: commandOutput(result), }), diff --git a/apps/server/src/provider/providerStatusCache.test.ts b/apps/server/src/provider/providerStatusCache.test.ts index cd7bfff273..66952445a7 100644 --- a/apps/server/src/provider/providerStatusCache.test.ts +++ b/apps/server/src/provider/providerStatusCache.test.ts @@ -222,7 +222,7 @@ it.layer(NodeServices.layer)("providerStatusCache", (it) => { version: null, status: "disabled", auth: { status: "unknown" }, - message: "Codex is disabled in T3 Code settings.", + message: "Codex is disabled in settings.", }); assert.deepStrictEqual( diff --git a/apps/server/src/textGeneration/OpenCodeTextGeneration.ts b/apps/server/src/textGeneration/OpenCodeTextGeneration.ts index 30f43ff1e4..33963cd5fb 100644 --- a/apps/server/src/textGeneration/OpenCodeTextGeneration.ts +++ b/apps/server/src/textGeneration/OpenCodeTextGeneration.ts @@ -215,7 +215,7 @@ export const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration" const session = yield* Effect.tryPromise({ try: () => client.session.create({ - title: `T3 Code ${input.operation}`, + title: `Zerops Mate ${input.operation}`, permission: [{ permission: "*", pattern: "*", action: "deny" }], }), catch: (cause) => diff --git a/apps/server/src/textGeneration/TextGenerationPrompts.test.ts b/apps/server/src/textGeneration/TextGenerationPrompts.test.ts index 86f6b54ab5..07f96f67f6 100644 --- a/apps/server/src/textGeneration/TextGenerationPrompts.test.ts +++ b/apps/server/src/textGeneration/TextGenerationPrompts.test.ts @@ -195,7 +195,7 @@ describe("buildThreadTitlePrompt", () => { }); expect(result.prompt).toContain( - "Regenerate the title for an existing T3 Code thread so the user can recognize it weeks later.", + "Regenerate the title for an existing thread so the user can recognize it weeks later.", ); expect(result.prompt).toContain('The previous title was "Investigate reconnect regressions".'); expect(result.prompt).toContain("Thread contents:"); diff --git a/apps/server/src/textGeneration/TextGenerationPrompts.ts b/apps/server/src/textGeneration/TextGenerationPrompts.ts index 3892813c68..b49ba33825 100644 --- a/apps/server/src/textGeneration/TextGenerationPrompts.ts +++ b/apps/server/src/textGeneration/TextGenerationPrompts.ts @@ -219,7 +219,7 @@ export interface ThreadTitlePromptInput { // Keep shared editorial rules in these two prompts in sync. Regeneration // intentionally adds guidance for thread history and the previous title. -const INITIAL_THREAD_TITLE_PROMPT = `Generate a title that will help the user recognize this T3 Code thread weeks later. +const INITIAL_THREAD_TITLE_PROMPT = `Generate a title that will help the user recognize this thread weeks later. Return JSON with keys title and needsRefinement. Set needsRefinement to true only if the subject is still unknown, such as an unresolved link, "fix this", or an unexplained attachment. Otherwise set it to false. @@ -245,7 +245,7 @@ Editorial rules: - When a URL or attachment is the only source of the subject, use available tools to inspect it. If it cannot be resolved, remain accurate rather than guessing.`; function regenerateThreadTitlePrompt(previousTitle: string): string { - return `Regenerate the title for an existing T3 Code thread so the user can recognize it weeks later. + return `Regenerate the title for an existing thread so the user can recognize it weeks later. The previous title was ${JSON.stringify(previousTitle)}. Return JSON with keys title and needsRefinement. Set needsRefinement to false. diff --git a/apps/server/src/vcs/GitVcsDriver.ts b/apps/server/src/vcs/GitVcsDriver.ts index 82ad336756..d82f25f5cd 100644 --- a/apps/server/src/vcs/GitVcsDriver.ts +++ b/apps/server/src/vcs/GitVcsDriver.ts @@ -766,10 +766,10 @@ export const makeVcsDriverShape = Effect.fn("makeGitVcsDriverShape")(function* ( const commitEnv: NodeJS.ProcessEnv = { ...process.env, GIT_INDEX_FILE: tempIndexPath, - GIT_AUTHOR_NAME: "T3 Code", - GIT_AUTHOR_EMAIL: "t3code@users.noreply.github.com", - GIT_COMMITTER_NAME: "T3 Code", - GIT_COMMITTER_EMAIL: "t3code@users.noreply.github.com", + GIT_AUTHOR_NAME: "Mate", + GIT_AUTHOR_EMAIL: "mate@zerops.io", + GIT_COMMITTER_NAME: "Mate", + GIT_COMMITTER_EMAIL: "mate@zerops.io", }; // Forced process termination can leave Git's private index lock behind. diff --git a/apps/server/src/zerops/ZeropsGitSpawner.test.ts b/apps/server/src/zerops/ZeropsGitSpawner.test.ts index c353e19bac..14cfe62eb0 100644 --- a/apps/server/src/zerops/ZeropsGitSpawner.test.ts +++ b/apps/server/src/zerops/ZeropsGitSpawner.test.ts @@ -153,12 +153,12 @@ describe("rewriteGitSpawn — the environment that crosses the wire", () => { HOME: "/home/zerops", ZCP_API_KEY: "secret", LC_ALL: "C", - GIT_AUTHOR_NAME: "T3 Code", + GIT_AUTHOR_NAME: "Zerops Mate", }, }); assert.include(remote, "LC_ALL=C"); // The whole `K=V` token is quoted as one word, which is what `env` reads. - assert.include(remote, "'GIT_AUTHOR_NAME=T3 Code'"); + assert.include(remote, "'GIT_AUTHOR_NAME=Zerops Mate'"); assert.notInclude(remote, "PATH="); assert.notInclude(remote, "HOME="); assert.notInclude(remote, "secret"); @@ -167,7 +167,7 @@ describe("rewriteGitSpawn — the environment that crosses the wire", () => { it("strips the trace2 event stream, whose file is local and whose watcher never fires", () => { const remote = remoteOf(["status"], { cwd: "/var/www/kanbandev", - env: { GIT_TRACE2_EVENT: "/tmp/t3-trace.json", GIT_AUTHOR_NAME: "T3 Code" }, + env: { GIT_TRACE2_EVENT: "/tmp/t3-trace.json", GIT_AUTHOR_NAME: "Zerops Mate" }, }); assert.notInclude(remote, "GIT_TRACE2_EVENT"); assert.include(remote, "GIT_AUTHOR_NAME"); diff --git a/docs/internals/zerops/fork.md b/docs/internals/zerops/fork.md index 5aa352313a..3df2066c6f 100644 --- a/docs/internals/zerops/fork.md +++ b/docs/internals/zerops/fork.md @@ -90,6 +90,14 @@ keys registered on the platform side: the sign-in hand-over asks for mode `zerop (`ZEROPS_HANDOVER_APP_MODE`), the value the platform client's registry serves — a rename there is a platform release, not a string sweep. +Copy is the other way round. What an agent is told about where it runs and what a person reads in +a message names the product Zerops Mate, never "T3 Code" — the owner's call on 2026-09-26. +`scripts/product-name.test.ts` parses every string, template and JSX text literal in +`apps/server/src` and the shared packages and fails on the old name, so a port that brings it back +is reworded in the same slice. Comments and vendor-facing identifiers stay: the Codex originator +`t3code_desktop`, the Grok OAuth referrer `t3code` and the ACP client names identify the client to +a vendor, and `t3.json` is the project file's name. + ## 5. How work is done — the zcp loop, transplanted - **Homes**: design → `../../../../zcp/docs/spec-mate.md`; measured facts → the ledger diff --git a/docs/internals/zerops/intake.md b/docs/internals/zerops/intake.md index 632185bebd..f6f1ecbfec 100644 --- a/docs/internals/zerops/intake.md +++ b/docs/internals/zerops/intake.md @@ -9,10 +9,10 @@ Rows 4 and 5 are the exceptions that prove the rule: the owner asked for **every every commit a verdict. The per-commit verdict lists live with the slices' reports, not here; this table keeps the decisions. -| Last-reviewed SHA | Date | Decisions | Open security candidates | -| --------------------------------------------------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | -| `f94a0d646ed78a4788e4af6417f74202a628a5e9` (tag `upstream-base-2026-08-28`) | 2026-08-28 | freeze; import list = `packages/effect-codex-app-server`, `packages/effect-acp` (both standalone; `imported.lock` landed 2026-08-29); no cherry-picks; no ideas | none | -| `827345a07a3d2348abc63e5215e57184024078d8` (`upstream/main`, 2026-09-02) | 2026-09-02 | first real intake. 180 upstream commits triaged; 27 planned picks + 1 prerequisite found mid-slice (`cb49e5d72`, the sole introducer of the OpenCode idle-reconciliation/cancellation API `62d39bf00` calls) = **28 ports** in 5 slices. Imported zone re-imported from this SHA. Taken: Claude model catalog moves into the remote manifest (`035428368`) + Fable 5.1 (`c17d02cff`); 10 orchestration/streaming perf commits; provider-runtime idle-CPU/event-leak, Grok and OpenCode ports; usage/pricing/git/contracts fixes; `41adccc83` (long thread IDs in HTTP routes). **Rejected: `c78ae50a5`** (remote web session cookies) — our cookies are host-only and every container has its own hostname, so the isolation it adds is already ours; its `environment-id` half self-heals here (`readPersistedEnvironmentId` already treats an empty file as absent) and is not separable from the `ServerEnvironmentIdentity` extraction the cookie rename needs. Skipped by moving the SHA: all `apps/web` UI (137 of 180 commits are client-surface-only and collide with the in-flight UI programme), mobile/desktop, pull-requests (deleted at the freeze), Electron 43 / Expo SDK 57 bumps | none | -| `c8f77e0d441264efb0acfac312e852c81ae3da83` (`upstream/main`, 2026-09-04) | 2026-09-05 | 250 upstream commits triaged. **Prerequisite in the import commit: vite-plus 0.2.2 → 0.3.0** — upstream's wire packages are formatted with 0.3.0's oxfmt, a byte-identical import fails `vp check` under 0.2.2, and the 0.3.0 reformat of the old import breaks the lock; neither half is green alone. Imported zone re-imported. **Ported: 47 + 8 recovered** in three slices — C1 owned core (15: ws slow-client budget, replay only the selected thread, pairing credentials out of read models, desktop-session replacement, authorization refresh without disconnect, static-asset caching under the base path, checkpoint summaries via numstat, projector/terminal/thread-summary perf, git patch prefixes, worktree removal timeout, SQLite error conditions); P1 provider (18 + 5) incl. **Google Antigravity** (`06336460c` + 10 follow-ups; offered like Claude and Codex; upstream's sign-in flow — the Google URL surfaces in the settings provider setup, the pasted callback is forwarded from inside the container to the ACP loopback listener; own synthetic SPI golden; the `mcpServers: []` matches Cursor/Grok); P2 provider (19 + 2) incl. **`/compact`** (`c5ba51d62`: Codex and OpenCode native, every other adapter via its slash command with a 10-minute settle), **Usage Limits tab** (`19d8ab2ae`, `1641b4aba`, `b34ff8f56`, `f1e90e388`; new typed capability `spi/usageLimitsSupport.ts`), Codex async questions, Claude Agent SDK 0.3.260, OpenCode approvals/stop/skills/perf. **Row 2 had moved the SHA past eight ported-zone or client-runtime commits it never ported** — `08aad594f`, `ea71a19d4`, `d0b19b32e`, `db4bf9497`, `80a14b658`, `9e646ad84`, `b883fc066`, `0e1570bde` — every one surfaced as a missing symbol under a later port and was recovered as its own `port:` commit (the two chores as ported-zone hunks only; `c37fd136edf` partially, its 24-line SQL statement counter only). `fork.md` §6 step 1 now names every ported-zone commit. SPI 2.2 → 2.3 (`account.rate-limits.updated` payload). **Rejected:** `1587f248d` turn token usage (PostHog sink unwired here, no UI consumer yet), `5b7d72aad` continue threads across self-update (mate's restart is zcp's unit restart; needs its own design over the seam), `ba3cb0773` auto-pull clean default branches (spec §6 does not say who owns the default branch in the container), `535557b3f`+`63f334baf` (attempt + revert), `a81a52afb`, `ca63d42d6`, `617edab65`. Named after landing, because the ported Antigravity picker tests asserted them: `acb599d2d` (mobile sub-provider subtitles — UI programme) and **`5392c9bb9` restore sticky new-thread selections (server migration 044 + decider + web + mobile + `shared/model` explicit option selections) — a fix candidate for the next slice**, the tests were pinned to the fork's semantics instead (`test(mobile): pin the ported Antigravity picker cases…`). **Skipped by moving the SHA:** ~150 web/mobile/desktop/marketing-only commits (the UI programme owns the client; the 8-commit web perf batch `19c1710a8` `887ece307` `5eab021a5` `b3e1d8859` `c7c1dfe4d` `dab5f6e6e` `cccd7e3c8` `da7e46d08` handed to it), pull-request commits (feature deleted), `cloud/*` relay-endpoint commits (`b90898077`, `99e3b721c`; S5-5 deletes that code), relay-credential commits (`246064993`, `088cc3f95`, `c75299ee2`; S5), Electron/Expo bumps. | none — Antigravity sign-in through `zcp agent mark-oauth` (spec §8) is a product slice, not a security gap | -| `9ea9c3d5d2c444133e3ddff40eecf38737951589` (`upstream/main`, 2026-09-18) | 2026-09-18 | **Owner instruction: port everything that lands on kept code.** 873 upstream commits triaged in five zone slices (provider, owned core, web, mobile, desktop+deps+CI) run as parallel worktrees; 531 `port:` + 1 `import:` commits landed. **Security first:** `95834d68a` — Claude title/commit-message generation ran `claude -p --dangerously-skip-permissions` in the project folder with the checkout's hooks and MCP config, on prompts carrying diffs and user text (prompt-injection reach into a container holding Zerops tokens); landed `1d0d876d3` with `52b2bf77a` + `5c6c1d67d`. Also `ac4f1a2b6` (redacted saves dropped inline provider secrets), `b6f72681d` (every linked host, internal ones included, was sent to Google's favicon service), `363cde411`, `793122797`, `ce4712d5b` (a push could serve a stale `index.html` via 304/etag), `8ef478eb0`, and `52e4b4429` redone by hand against our lock — `pnpm audit` 85 (1 critical, 54 high) → 4 (the rest need major Expo bumps). **Toolchain, one commit because neither half is green alone (`2a26e8e76`):** Effect beta.103 → rc.115, TypeScript 6 → 7.0.2 (native-preview dropped, `tsc` replaces `tsgo` in every package script), `@effect/tsgo` 0.41, the effect/@effect-vitest patches moved to upstream's rc.115 versions, wire packages re-imported at `9ea9c3d5d`; ~330 owned files migrated mechanically (`Schema.TaggedErrorClass` → `TaggedError` ×616, capitalised `Config.*`, `Flag.*`, `ByteSize`, `NetAddress`), JSON Schema kept closed with `onExcessProperty: "error"` since rc.113 opens objects by default. Electron 41 → 44.4.2, Expo SDK 56 → 57 + RN 0.86. **Own bugs found by ported tooling:** upstream's Hermes lint rule (`37a8ab2b2`) caught 14 `toSorted`/`toReversed` calls in `zerops/**` client-runtime + the mobile keyboard dispatcher that would throw on mobile; the ported review-diff preview (`26894dda7`) dropped same-size edits written in the same second as the index copy. **Ports of note:** provider — thinking traces (`052c7ae53`, no SPI bump, Claude goldens unmoved because no recorded turn thinks), the rewind chain (`fd5553f1a` → `efccda9ac` → `eed974c12`; before it every Mate revert was refused), usage-limit/expired-login naming, `1abc717f0`+`95139254b` (Codex threads that would not resume), model manifest (`bc03c3640`, `bfef973d9`, `1f73a89fc`, `315b72371` — live for every Mate on merge); core — paragraph streaming (`c07575f57`+`1bbca0e78` as an environment-wide setting, the fork has no per-project settings), background clone with progress, request-shaped titles, Forgejo/Gitea source control (`6fd68f5c3`, source-control half), notifications/badges, composer shortcuts, OTLP protocol+headers; web — queue-while-working integrated with the fork's stash (`cc839c42b`), per-thread reading position, grouped thought rows (`22539f2a4` chain, no shimmer per R6), incremental markdown/highlighting, `03c6cd8ba` (copy over plain HTTP), `e62868393`; mobile — Expo 57, `36c48a6b7` (a transport-failed send dropped the message), the legendapp iOS scroll patch rebuilt, Material You. **Migrations:** upstream 044/049/052 → the fork's 049/050/051 (the fork's 044–048 are its own; registry keys on `id_name`, live DBs already ran 048); next free 052. **SPI stays 2.3**; `spi.md` §6 updated for the `cliproxyUsageLimits` removal (`0a89364f1`), compat row 3 added. **Rejected:** `b4620d595` (refuses every file restore with worktrees off), `3b75e607e` (never-expiring dev token), `a01b227d6`/`32e8b2584` (signed URLs for arbitrary absolute paths; a server-side GitHub media proxy), `b906ce2d7`/`5b7d72aad` (self-update continuation), `c7f23c466`/`8f90b380f` (single-executable installs — zcp owns the binary), Knip (`126ea5c3b`, `d2c3e2e5d`: 199 unused files on this tree), upstream's release pipeline/nightlies, Macroscope+CodeRabbit bot config (`.macroscope` is a stale upstream copy; no bot reviews this fork), upstream user guides (ours are the Mate's). **Skipped by moving the SHA:** deleted-feature commits (upstream's pullRequest service ×24, preview browser + MCP + devices, Tailscale, T3 cloud reach/Clerk, local spawn, `packages/ssh`, worktree setup ×11, marketing), Windows-only fixes. **Deferred with a reason, not skipped:** upstream UI on surfaces the fork redesigned — project icons, sidebar drag, inline file previews (`4fed6cfb3`), the Tiptap composer (`d359e94ca`), the Android Material redesign (`e106fe95c` + 12 dependents), Android push (`6c583620f`, needs the S5 relay + Firebase), and the open-source license notices screen (`4a4c6dd2a`, with `f8500f112`) — it is mobile's settings and mobile is a stub in this tree, so the fork's attributions stay in `apps/web/THIRD_PARTY_NOTICES.md` and `apps/mobile/modules/t3-terminal/THIRD_PARTY_NOTICES.md` until mobile ships; its web follow-up `e47a11e1e` needs nothing, the fork's follow-up control is already the `Select` it moved to and there is no license control here to align. | none | -| `7a12aff471ffe2b22b9fee495b04b32c43f45a37` (`upstream/main`, 2026-09-25) | 2026-09-25 | **Owner instruction: adopt as much as possible, but only what makes sense given how Zerops works.** 272 upstream commits since row 4. 63 set aside mechanically — deleted features (devices ×12, preview browser + its MCP ×4, T3 Connect/tunnels ×2, 30 that touch only files the fork deleted), Windows-only ×2, upstream CI/release/bot config ×12, marketing, and `f25a8e4b7` already ported — and the other 208 given a verdict in four zone slices run as parallel worktrees (provider, core, web, mobile): **157 `port:` + 1 `import:`** landed, with three fixes where slices met (a migration test on a removed helper, three vendor colours for the theme ledger, a sidebar export the merge dropped). **The hard fork stays hard:** no upstream remote; each commit was built as a patch in a scratch clone and 3-way applied with only its preimage blobs written (`fork.md` §6); `imported-lock --write` cannot resolve upstream refs here, so the lock was written from the scratch clone's tree OIDs and verified with `--check`. **Codex:** `d5d48742c` "requires Codex 0.156" only in its manifest range — the regenerated protocol was measured against the image's codex-cli 0.155.1 (the only removal is `thread/rollback`; real 0.155.1 messages decode), so the wire packages import at `7a12aff47` and the manifest floor is `>=0.155.1`; Claude's floor is 2.1.278, what the image ships (upstream 2.1.280). **Security/robustness:** `c03b24026` (fetch failures diagnosed without remote output — the fork's remote git paths already kept fixed text), `6d68677ff` (secrets restored when settings persistence fails), `80d9c181d` (legacy message-sent events without `turnId` no longer stop startup; upstream's `context` field stays out), `d06f0ff10` (SQLite prepare retry, hand-ported to `apps/server/src/persistence/NodeSqliteClient.ts`), `e4eb9977f`, `869347bc2`, `b2b43bef7` (upstream's review-diff race fix replaces the fork's row-4 one). **Ports of note:** provider — compatibility advisories from the fork's own manifest on `zeropsio/mate` (`t3CodeRange` means Mate versions; no pinned-install button, the image owns the CLIs), Claude banked resets (api.anthropic.com only), shared provider sign-in flows (they serve Antigravity; the Zerops agent sign-in is untouched), usage history for Cursor/OpenCode/Antigravity (`e5a46d6c5`; the Keychain path left out — the server never runs on macOS; new SPI capability `driverHomes.antigravityProfileDirectory`; usage contract 5 → 6, still merging from 4), Grok joins the existing one-click CLI updates, Codex runtime instructions through `additionalContext` (0.155.1 supports it); SPI stays 2.3, compat row 4 added. Core — per-thread auto-settle (**upstream 054 → fork migration 052**; next free 053), undo for settle/snooze/archive/unpin, `mod+[`/`mod+]` history and `mod+u` usage, OTLP logs + kill switch + malformed-attributes tolerance, desktop OTLP + compile cache + background sync of running threads, worktree submodule mode environment-wide (`worktreeSubmodules`), GPT-6 Luna text generation, relay delegated thread ids. Web — upstream's ui-kit pass (component variants/sizes and the call sites that restyled them) with its guards as rules R9–R11 (`design-system.md`): `t3code/no-restyle` over @shadcn/lint, `no-unknown-classes` + `require-static-classes`, `no-arbitrary-values`, each an error with an F6 baseline (329 / 3 / 4 / 265 entries; 75 restyles and 141 arbitrary values are Zerops); theme tokens at call sites (34 R3 entries retired); vite-plus 0.3.0 → 0.3.3; a one-line shell block in a reply runs in the thread terminal on click (closed fence, one line, no control characters, not while streaming). Mobile — native patches rebuilt for expo-modules-core 57.0.18 and expo-notifications 57.0.19 (stock 57.0.19 still drops notification taps), platform header/menu splits, Home on the recycling list, render-error recovery. **Integration with the fork's own work in flight:** the 12 usage commits that landed meanwhile (usage by person, project and Mate) keep their scope filter and per-environment totals beside the new readers; their `UsagePage.test.tsx` stays although upstream deleted its static-markup predecessor; a stale environment in their test is now `USAGE_MERGE_COMPATIBLE_SINCE - 1`. **Rejected/skipped:** `dcdf5e6a0` (single-executable ESM scan), `742173a13` (per-project settings resolver — the fork's `t3.json` default already has its precedence), upstream pull-request-service commits ×6, `d4a33457c`/`a107f8a07` (the desktop's own backend and relay discovery), `68fb7f4b8` (upstream's environment/provider updaters — `zerops.mate.update` and image-owned CLIs), `7a326c244` (dev client on upstream's EAS project), app version bumps, `6cc7f7006`/`c0912debc`, `da6a85b13`/`7c2702d68` (no panel-animation setting), `b3de243d5` (Windows setup action), `b9199617d` (Tailwind 4.3.0 emits one block per class — take it with `1f7a3c11c` in any 4.3.3+ bump), `82cd1d1aa` (model favourites the fork never took). **Deferred with a reason:** `9a609a4e4` (the undo notice moves into the sidebar, the fork's redesigned surface — the toast stays), `dca84efb5`/`9030a60ea`/`266d70cc4` (Tiptap composer), `0f1b572b9` (mobile theme on the Material redesign), the Material-redesign dependents (`dec073228`, `7230f6b1b`, `4fb9dfc8b`'s ScreenHeader with `989bde889`/`54bbed660`/`7ee60f4bc`/`aba1c6352`/`88b9226d2`, `21be723ad`), `11e91f126`/`9c524d577` (showcase captures need Android push), `1c1270663` (project icons). **Partial:** `568c9bc4d` (Effect language-service suggestions: 94 files take the rewrite, 48 hunks on fork-diverged code keep the fork's version; `schemaNumber` off as upstream). **Open for the owner:** the in-app CLI updaters still exist although the image owns the CLIs; agents and some messages still say "T3 Code"; `apps/mobile/app.config.ts` still names upstream's EAS project; a visual pass over the ui-kit changes (disabled controls at 64 % opacity, provider badges 7 → 10 px, right-panel count 9 → 10 px) was not done. | none | +| Last-reviewed SHA | Date | Decisions | Open security candidates | +| --------------------------------------------------------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | +| `f94a0d646ed78a4788e4af6417f74202a628a5e9` (tag `upstream-base-2026-08-28`) | 2026-08-28 | freeze; import list = `packages/effect-codex-app-server`, `packages/effect-acp` (both standalone; `imported.lock` landed 2026-08-29); no cherry-picks; no ideas | none | +| `827345a07a3d2348abc63e5215e57184024078d8` (`upstream/main`, 2026-09-02) | 2026-09-02 | first real intake. 180 upstream commits triaged; 27 planned picks + 1 prerequisite found mid-slice (`cb49e5d72`, the sole introducer of the OpenCode idle-reconciliation/cancellation API `62d39bf00` calls) = **28 ports** in 5 slices. Imported zone re-imported from this SHA. Taken: Claude model catalog moves into the remote manifest (`035428368`) + Fable 5.1 (`c17d02cff`); 10 orchestration/streaming perf commits; provider-runtime idle-CPU/event-leak, Grok and OpenCode ports; usage/pricing/git/contracts fixes; `41adccc83` (long thread IDs in HTTP routes). **Rejected: `c78ae50a5`** (remote web session cookies) — our cookies are host-only and every container has its own hostname, so the isolation it adds is already ours; its `environment-id` half self-heals here (`readPersistedEnvironmentId` already treats an empty file as absent) and is not separable from the `ServerEnvironmentIdentity` extraction the cookie rename needs. Skipped by moving the SHA: all `apps/web` UI (137 of 180 commits are client-surface-only and collide with the in-flight UI programme), mobile/desktop, pull-requests (deleted at the freeze), Electron 43 / Expo SDK 57 bumps | none | +| `c8f77e0d441264efb0acfac312e852c81ae3da83` (`upstream/main`, 2026-09-04) | 2026-09-05 | 250 upstream commits triaged. **Prerequisite in the import commit: vite-plus 0.2.2 → 0.3.0** — upstream's wire packages are formatted with 0.3.0's oxfmt, a byte-identical import fails `vp check` under 0.2.2, and the 0.3.0 reformat of the old import breaks the lock; neither half is green alone. Imported zone re-imported. **Ported: 47 + 8 recovered** in three slices — C1 owned core (15: ws slow-client budget, replay only the selected thread, pairing credentials out of read models, desktop-session replacement, authorization refresh without disconnect, static-asset caching under the base path, checkpoint summaries via numstat, projector/terminal/thread-summary perf, git patch prefixes, worktree removal timeout, SQLite error conditions); P1 provider (18 + 5) incl. **Google Antigravity** (`06336460c` + 10 follow-ups; offered like Claude and Codex; upstream's sign-in flow — the Google URL surfaces in the settings provider setup, the pasted callback is forwarded from inside the container to the ACP loopback listener; own synthetic SPI golden; the `mcpServers: []` matches Cursor/Grok); P2 provider (19 + 2) incl. **`/compact`** (`c5ba51d62`: Codex and OpenCode native, every other adapter via its slash command with a 10-minute settle), **Usage Limits tab** (`19d8ab2ae`, `1641b4aba`, `b34ff8f56`, `f1e90e388`; new typed capability `spi/usageLimitsSupport.ts`), Codex async questions, Claude Agent SDK 0.3.260, OpenCode approvals/stop/skills/perf. **Row 2 had moved the SHA past eight ported-zone or client-runtime commits it never ported** — `08aad594f`, `ea71a19d4`, `d0b19b32e`, `db4bf9497`, `80a14b658`, `9e646ad84`, `b883fc066`, `0e1570bde` — every one surfaced as a missing symbol under a later port and was recovered as its own `port:` commit (the two chores as ported-zone hunks only; `c37fd136edf` partially, its 24-line SQL statement counter only). `fork.md` §6 step 1 now names every ported-zone commit. SPI 2.2 → 2.3 (`account.rate-limits.updated` payload). **Rejected:** `1587f248d` turn token usage (PostHog sink unwired here, no UI consumer yet), `5b7d72aad` continue threads across self-update (mate's restart is zcp's unit restart; needs its own design over the seam), `ba3cb0773` auto-pull clean default branches (spec §6 does not say who owns the default branch in the container), `535557b3f`+`63f334baf` (attempt + revert), `a81a52afb`, `ca63d42d6`, `617edab65`. Named after landing, because the ported Antigravity picker tests asserted them: `acb599d2d` (mobile sub-provider subtitles — UI programme) and **`5392c9bb9` restore sticky new-thread selections (server migration 044 + decider + web + mobile + `shared/model` explicit option selections) — a fix candidate for the next slice**, the tests were pinned to the fork's semantics instead (`test(mobile): pin the ported Antigravity picker cases…`). **Skipped by moving the SHA:** ~150 web/mobile/desktop/marketing-only commits (the UI programme owns the client; the 8-commit web perf batch `19c1710a8` `887ece307` `5eab021a5` `b3e1d8859` `c7c1dfe4d` `dab5f6e6e` `cccd7e3c8` `da7e46d08` handed to it), pull-request commits (feature deleted), `cloud/*` relay-endpoint commits (`b90898077`, `99e3b721c`; S5-5 deletes that code), relay-credential commits (`246064993`, `088cc3f95`, `c75299ee2`; S5), Electron/Expo bumps. | none — Antigravity sign-in through `zcp agent mark-oauth` (spec §8) is a product slice, not a security gap | +| `9ea9c3d5d2c444133e3ddff40eecf38737951589` (`upstream/main`, 2026-09-18) | 2026-09-18 | **Owner instruction: port everything that lands on kept code.** 873 upstream commits triaged in five zone slices (provider, owned core, web, mobile, desktop+deps+CI) run as parallel worktrees; 531 `port:` + 1 `import:` commits landed. **Security first:** `95834d68a` — Claude title/commit-message generation ran `claude -p --dangerously-skip-permissions` in the project folder with the checkout's hooks and MCP config, on prompts carrying diffs and user text (prompt-injection reach into a container holding Zerops tokens); landed `1d0d876d3` with `52b2bf77a` + `5c6c1d67d`. Also `ac4f1a2b6` (redacted saves dropped inline provider secrets), `b6f72681d` (every linked host, internal ones included, was sent to Google's favicon service), `363cde411`, `793122797`, `ce4712d5b` (a push could serve a stale `index.html` via 304/etag), `8ef478eb0`, and `52e4b4429` redone by hand against our lock — `pnpm audit` 85 (1 critical, 54 high) → 4 (the rest need major Expo bumps). **Toolchain, one commit because neither half is green alone (`2a26e8e76`):** Effect beta.103 → rc.115, TypeScript 6 → 7.0.2 (native-preview dropped, `tsc` replaces `tsgo` in every package script), `@effect/tsgo` 0.41, the effect/@effect-vitest patches moved to upstream's rc.115 versions, wire packages re-imported at `9ea9c3d5d`; ~330 owned files migrated mechanically (`Schema.TaggedErrorClass` → `TaggedError` ×616, capitalised `Config.*`, `Flag.*`, `ByteSize`, `NetAddress`), JSON Schema kept closed with `onExcessProperty: "error"` since rc.113 opens objects by default. Electron 41 → 44.4.2, Expo SDK 56 → 57 + RN 0.86. **Own bugs found by ported tooling:** upstream's Hermes lint rule (`37a8ab2b2`) caught 14 `toSorted`/`toReversed` calls in `zerops/**` client-runtime + the mobile keyboard dispatcher that would throw on mobile; the ported review-diff preview (`26894dda7`) dropped same-size edits written in the same second as the index copy. **Ports of note:** provider — thinking traces (`052c7ae53`, no SPI bump, Claude goldens unmoved because no recorded turn thinks), the rewind chain (`fd5553f1a` → `efccda9ac` → `eed974c12`; before it every Mate revert was refused), usage-limit/expired-login naming, `1abc717f0`+`95139254b` (Codex threads that would not resume), model manifest (`bc03c3640`, `bfef973d9`, `1f73a89fc`, `315b72371` — live for every Mate on merge); core — paragraph streaming (`c07575f57`+`1bbca0e78` as an environment-wide setting, the fork has no per-project settings), background clone with progress, request-shaped titles, Forgejo/Gitea source control (`6fd68f5c3`, source-control half), notifications/badges, composer shortcuts, OTLP protocol+headers; web — queue-while-working integrated with the fork's stash (`cc839c42b`), per-thread reading position, grouped thought rows (`22539f2a4` chain, no shimmer per R6), incremental markdown/highlighting, `03c6cd8ba` (copy over plain HTTP), `e62868393`; mobile — Expo 57, `36c48a6b7` (a transport-failed send dropped the message), the legendapp iOS scroll patch rebuilt, Material You. **Migrations:** upstream 044/049/052 → the fork's 049/050/051 (the fork's 044–048 are its own; registry keys on `id_name`, live DBs already ran 048); next free 052. **SPI stays 2.3**; `spi.md` §6 updated for the `cliproxyUsageLimits` removal (`0a89364f1`), compat row 3 added. **Rejected:** `b4620d595` (refuses every file restore with worktrees off), `3b75e607e` (never-expiring dev token), `a01b227d6`/`32e8b2584` (signed URLs for arbitrary absolute paths; a server-side GitHub media proxy), `b906ce2d7`/`5b7d72aad` (self-update continuation), `c7f23c466`/`8f90b380f` (single-executable installs — zcp owns the binary), Knip (`126ea5c3b`, `d2c3e2e5d`: 199 unused files on this tree), upstream's release pipeline/nightlies, Macroscope+CodeRabbit bot config (`.macroscope` is a stale upstream copy; no bot reviews this fork), upstream user guides (ours are the Mate's). **Skipped by moving the SHA:** deleted-feature commits (upstream's pullRequest service ×24, preview browser + MCP + devices, Tailscale, T3 cloud reach/Clerk, local spawn, `packages/ssh`, worktree setup ×11, marketing), Windows-only fixes. **Deferred with a reason, not skipped:** upstream UI on surfaces the fork redesigned — project icons, sidebar drag, inline file previews (`4fed6cfb3`), the Tiptap composer (`d359e94ca`), the Android Material redesign (`e106fe95c` + 12 dependents), Android push (`6c583620f`, needs the S5 relay + Firebase), and the open-source license notices screen (`4a4c6dd2a`, with `f8500f112`) — it is mobile's settings and mobile is a stub in this tree, so the fork's attributions stay in `apps/web/THIRD_PARTY_NOTICES.md` and `apps/mobile/modules/t3-terminal/THIRD_PARTY_NOTICES.md` until mobile ships; its web follow-up `e47a11e1e` needs nothing, the fork's follow-up control is already the `Select` it moved to and there is no license control here to align. | none | +| `7a12aff471ffe2b22b9fee495b04b32c43f45a37` (`upstream/main`, 2026-09-25) | 2026-09-25 | **Owner instruction: adopt as much as possible, but only what makes sense given how Zerops works.** 272 upstream commits since row 4. 63 set aside mechanically — deleted features (devices ×12, preview browser + its MCP ×4, T3 Connect/tunnels ×2, 30 that touch only files the fork deleted), Windows-only ×2, upstream CI/release/bot config ×12, marketing, and `f25a8e4b7` already ported — and the other 208 given a verdict in four zone slices run as parallel worktrees (provider, core, web, mobile): **157 `port:` + 1 `import:`** landed, with three fixes where slices met (a migration test on a removed helper, three vendor colours for the theme ledger, a sidebar export the merge dropped). **The hard fork stays hard:** no upstream remote; each commit was built as a patch in a scratch clone and 3-way applied with only its preimage blobs written (`fork.md` §6); `imported-lock --write` cannot resolve upstream refs here, so the lock was written from the scratch clone's tree OIDs and verified with `--check`. **Codex:** `d5d48742c` "requires Codex 0.156" only in its manifest range — the regenerated protocol was measured against the image's codex-cli 0.155.1 (the only removal is `thread/rollback`; real 0.155.1 messages decode), so the wire packages import at `7a12aff47` and the manifest floor is `>=0.155.1`; Claude's floor is 2.1.278, what the image ships (upstream 2.1.280). **Security/robustness:** `c03b24026` (fetch failures diagnosed without remote output — the fork's remote git paths already kept fixed text), `6d68677ff` (secrets restored when settings persistence fails), `80d9c181d` (legacy message-sent events without `turnId` no longer stop startup; upstream's `context` field stays out), `d06f0ff10` (SQLite prepare retry, hand-ported to `apps/server/src/persistence/NodeSqliteClient.ts`), `e4eb9977f`, `869347bc2`, `b2b43bef7` (upstream's review-diff race fix replaces the fork's row-4 one). **Ports of note:** provider — compatibility advisories from the fork's own manifest on `zeropsio/mate` (`t3CodeRange` means Mate versions; no pinned-install button, the image owns the CLIs), Claude banked resets (api.anthropic.com only), shared provider sign-in flows (they serve Antigravity; the Zerops agent sign-in is untouched), usage history for Cursor/OpenCode/Antigravity (`e5a46d6c5`; the Keychain path left out — the server never runs on macOS; new SPI capability `driverHomes.antigravityProfileDirectory`; usage contract 5 → 6, still merging from 4), Grok joins the existing one-click CLI updates, Codex runtime instructions through `additionalContext` (0.155.1 supports it); SPI stays 2.3, compat row 4 added. Core — per-thread auto-settle (**upstream 054 → fork migration 052**; next free 053), undo for settle/snooze/archive/unpin, `mod+[`/`mod+]` history and `mod+u` usage, OTLP logs + kill switch + malformed-attributes tolerance, desktop OTLP + compile cache + background sync of running threads, worktree submodule mode environment-wide (`worktreeSubmodules`), GPT-6 Luna text generation, relay delegated thread ids. Web — upstream's ui-kit pass (component variants/sizes and the call sites that restyled them) with its guards as rules R9–R11 (`design-system.md`): `t3code/no-restyle` over @shadcn/lint, `no-unknown-classes` + `require-static-classes`, `no-arbitrary-values`, each an error with an F6 baseline (329 / 3 / 4 / 265 entries; 75 restyles and 141 arbitrary values are Zerops); theme tokens at call sites (34 R3 entries retired); vite-plus 0.3.0 → 0.3.3; a one-line shell block in a reply runs in the thread terminal on click (closed fence, one line, no control characters, not while streaming). Mobile — native patches rebuilt for expo-modules-core 57.0.18 and expo-notifications 57.0.19 (stock 57.0.19 still drops notification taps), platform header/menu splits, Home on the recycling list, render-error recovery. **Integration with the fork's own work in flight:** the 12 usage commits that landed meanwhile (usage by person, project and Mate) keep their scope filter and per-environment totals beside the new readers; their `UsagePage.test.tsx` stays although upstream deleted its static-markup predecessor; a stale environment in their test is now `USAGE_MERGE_COMPATIBLE_SINCE - 1`. **Rejected/skipped:** `dcdf5e6a0` (single-executable ESM scan), `742173a13` (per-project settings resolver — the fork's `t3.json` default already has its precedence), upstream pull-request-service commits ×6, `d4a33457c`/`a107f8a07` (the desktop's own backend and relay discovery), `68fb7f4b8` (upstream's environment/provider updaters — `zerops.mate.update` and image-owned CLIs), `7a326c244` (dev client on upstream's EAS project), app version bumps, `6cc7f7006`/`c0912debc`, `da6a85b13`/`7c2702d68` (no panel-animation setting), `b3de243d5` (Windows setup action), `b9199617d` (Tailwind 4.3.0 emits one block per class — take it with `1f7a3c11c` in any 4.3.3+ bump), `82cd1d1aa` (model favourites the fork never took). **Deferred with a reason:** `9a609a4e4` (the undo notice moves into the sidebar, the fork's redesigned surface — the toast stays), `dca84efb5`/`9030a60ea`/`266d70cc4` (Tiptap composer), `0f1b572b9` (mobile theme on the Material redesign), the Material-redesign dependents (`dec073228`, `7230f6b1b`, `4fb9dfc8b`'s ScreenHeader with `989bde889`/`54bbed660`/`7ee60f4bc`/`aba1c6352`/`88b9226d2`, `21be723ad`), `11e91f126`/`9c524d577` (showcase captures need Android push), `1c1270663` (project icons). **Partial:** `568c9bc4d` (Effect language-service suggestions: 94 files take the rewrite, 48 hunks on fork-diverged code keep the fork's version; `schemaNumber` off as upstream). **Open for the owner:** the in-app CLI updaters still exist although the image owns the CLIs; `apps/mobile/app.config.ts` still names upstream's EAS project; a visual pass over the ui-kit changes (disabled controls at 64 % opacity, provider badges 7 → 10 px, right-panel count 9 → 10 px) was not done. **Decided after the row (2026-09-26):** "T3 Code" leaves agent instructions and messages (`fork.md` §4.1, guarded by `scripts/product-name.test.ts`). | none | diff --git a/packages/contracts/src/relay.ts b/packages/contracts/src/relay.ts index 10b81e6ea8..b630a985f4 100644 --- a/packages/contracts/src/relay.ts +++ b/packages/contracts/src/relay.ts @@ -838,7 +838,7 @@ export const RelayApi = HttpApi.make("RelayApi") RelayTokenGroup, RelayServerGroup, ) - .annotate(OpenApi.Title, "T3 Code Relay API") + .annotate(OpenApi.Title, "Zerops Mate Relay API") .annotate(OpenApi.Version, "1.0.0") .annotate( OpenApi.Description, diff --git a/packages/contracts/src/settings.ts b/packages/contracts/src/settings.ts index 8eed731dd8..8e18b25e3c 100644 --- a/packages/contracts/src/settings.ts +++ b/packages/contracts/src/settings.ts @@ -590,7 +590,7 @@ export const OpenCodeSettings = makeProviderSettingsSchema( Schema.withDecodingDefault(Effect.succeed("")), Schema.annotateKey({ title: "Server URL", - description: "Leave blank to let T3 Code spawn the server when needed.", + description: "Leave blank to let Zerops Mate spawn the server when needed.", providerSettingsForm: { placeholder: "http://127.0.0.1:4096", clearWhenEmpty: "omit", diff --git a/packages/contracts/src/t3ProjectFile.ts b/packages/contracts/src/t3ProjectFile.ts index 8197f2c519..0f4cb35474 100644 --- a/packages/contracts/src/t3ProjectFile.ts +++ b/packages/contracts/src/t3ProjectFile.ts @@ -26,10 +26,10 @@ const trimmedNonEmpty = (annotations: { readonly description: string }, maxLengt export const T3ProjectFileScript = Schema.Struct({ name: trimmedNonEmpty({ - description: "Display name for the script, shown in the T3 Code scripts menu.", + description: "Display name for the script, shown in the Zerops Mate scripts menu.", }), command: trimmedNonEmpty({ - description: "Shell command executed in a T3 Code terminal at the project root.", + description: "Shell command executed in a Zerops Mate terminal at the project root.", }), icon: Schema.optionalKey( ProjectScriptIcon.annotate({ @@ -43,7 +43,7 @@ export const T3ProjectFileScript = Schema.Struct({ }), ), }).annotate({ - description: "A project script that team members can import into T3 Code.", + description: "A project script that team members can import into Zerops Mate.", }); export type T3ProjectFileScript = typeof T3ProjectFileScript.Type; @@ -57,7 +57,7 @@ export const T3ProjectFile = Schema.Struct({ trimmedNonEmpty( { description: - 'Workspace-relative path to the project icon (e.g. "assets/logo.svg"). Checked before T3 Code\'s built-in icon locations.', + 'Workspace-relative path to the project icon (e.g. "assets/logo.svg"). Checked before Zerops Mate\'s built-in icon locations.', }, T3_PROJECT_FILE_PATH_MAX_LENGTH, ), @@ -65,7 +65,7 @@ export const T3ProjectFile = Schema.Struct({ defaultThreadEnvMode: Schema.optionalKey( ThreadEnvMode.annotate({ description: - 'Where new threads start for this repository: "worktree" for a fresh git worktree, "local" for the current checkout. A per-project setting in T3 Code overrides this; when neither is set, the global default applies.', + 'Where new threads start for this repository: "worktree" for a fresh git worktree, "local" for the current checkout. A per-project setting in Zerops Mate overrides this; when neither is set, the global default applies.', }), ), worktreeSubmodules: Schema.optionalKey( @@ -77,13 +77,13 @@ export const T3ProjectFile = Schema.Struct({ scripts: Schema.optionalKey( Schema.Array(T3ProjectFileScript) .annotate({ - description: "Project scripts shared with everyone who opens this repository in T3 Code.", + description: + "Project scripts shared with everyone who opens this repository in Zerops Mate.", }) .check(Schema.isMaxLength(T3_PROJECT_FILE_MAX_SCRIPTS)), ), }).annotate({ title: "T3 project file", - description: - "Checked-in project configuration for T3 Code (t3.json at the repository root). See https://t3.codes for documentation.", + description: "Checked-in project configuration for Zerops Mate (t3.json at the repository root).", }); export type T3ProjectFile = typeof T3ProjectFile.Type; diff --git a/packages/shared/src/relayClient.ts b/packages/shared/src/relayClient.ts index 4d1ce98808..3574cfefc2 100644 --- a/packages/shared/src/relayClient.ts +++ b/packages/shared/src/relayClient.ts @@ -366,7 +366,7 @@ export const makeCloudflaredRelayClient = Effect.fn("cloudflared.make")(function if (!releaseAsset) { return yield* new RelayClientInstallError({ reason: "unsupported_platform", - message: `T3 Code does not provide a managed relay client binary for ${platform}-${arch}.`, + message: `Zerops Mate does not provide a managed relay client binary for ${platform}-${arch}.`, }); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c883e7f478..e6ca2b1e8e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -913,6 +913,9 @@ importers: '@types/pngjs': specifier: 6.0.5 version: 6.0.5 + oxc-parser: + specifier: 0.148.0 + version: 0.148.0 vite-plus: specifier: 'catalog:' version: 0.3.3(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@7.0.2))(terser@5.48.0)(typescript@7.0.2)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) @@ -11047,8 +11050,7 @@ snapshots: '@oxc-project/types@0.139.0': {} - '@oxc-project/types@0.148.0': - optional: true + '@oxc-project/types@0.148.0': {} '@oxc-project/types@0.150.0': {} @@ -16257,7 +16259,6 @@ snapshots: '@oxc-parser/binding-win32-arm64-msvc': 0.148.0 '@oxc-parser/binding-win32-ia32-msvc': 0.148.0 '@oxc-parser/binding-win32-x64-msvc': 0.148.0 - optional: true oxfmt@0.68.0(vite-plus@0.3.3(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@7.0.2))(terser@5.48.0)(typescript@7.0.2)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)): dependencies: diff --git a/scripts/package.json b/scripts/package.json index b84e635012..1d546a5f4f 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -19,6 +19,7 @@ "devDependencies": { "@effect/vitest": "catalog:", "@types/pngjs": "6.0.5", + "oxc-parser": "0.148.0", "vite-plus": "catalog:" } } diff --git a/scripts/product-name.test.ts b/scripts/product-name.test.ts new file mode 100644 index 0000000000..2d82b356c8 --- /dev/null +++ b/scripts/product-name.test.ts @@ -0,0 +1,124 @@ +// The server and the shared packages name the product Zerops Mate, never +// "T3 Code": what an agent is told about where it runs, and what a person +// reads in a provider status, a compatibility advisory or a CLI description. +// Upstream ports bring the old name back with every intake, so this scans +// every string, template and JSX text literal there. Comments are not copy +// and are not scanned; neither are identifiers such as the Codex originator +// `t3code_desktop` or the Grok OAuth referrer `t3code`, which name the client +// to a vendor and do not spell the product name. +import * as NodeServices from "@effect/platform-node/NodeServices"; +import { assert, describe, it } from "@effect/vitest"; +import * as Effect from "effect/Effect"; +import * as FileSystem from "effect/FileSystem"; +import * as Path from "effect/Path"; +import type { PlatformError } from "effect/PlatformError"; +import { parseSync } from "oxc-parser"; + +const repoRootUrl = new URL("..", import.meta.url); +const SCANNED_ROOTS = [ + "apps/server/src", + "packages/contracts/src", + "packages/shared/src", + "packages/client-runtime/src", +]; +// The vocabulary table spells the old name in order to ban it (design-system R4). +const VOCABULARY_TABLE = "packages/shared/src/legacyVocabulary.ts"; +const OLD_NAME = /\bT3 Code\b/u; + +interface AstNode { + readonly type: string; + readonly start: number; + readonly value?: unknown; +} + +function literalText(node: AstNode): string | undefined { + if (node.type === "Literal" && typeof node.value === "string") return node.value; + if (node.type === "JSXText" && typeof node.value === "string") return node.value; + if (node.type === "TemplateElement") { + const value = node.value as { readonly cooked?: string | null; readonly raw: string }; + return value.cooked ?? value.raw; + } + return undefined; +} + +function isAstNode(value: unknown): value is AstNode { + return typeof value === "object" && value !== null && typeof (value as AstNode).type === "string"; +} + +export function collectOldNameLiterals(source: string, file: string): ReadonlyArray { + const { program, errors } = parseSync(file, source); + if (errors.length > 0) return [`${file}: does not parse (${errors[0]!.message})`]; + const findings: Array = []; + const visit = (value: unknown): void => { + if (Array.isArray(value)) { + for (const item of value) visit(item); + return; + } + if (!isAstNode(value)) return; + const text = literalText(value); + if (text !== undefined && OLD_NAME.test(text)) { + const line = source.slice(0, value.start).split("\n").length; + findings.push(`${file}:${line}: ${text.trim().split("\n")[0]}`); + } + for (const [key, child] of Object.entries(value)) { + if (key !== "parent") visit(child); + } + }; + visit(program); + return findings; +} + +function collectSourceFiles( + dir: string, +): Effect.Effect, PlatformError, FileSystem.FileSystem | Path.Path> { + return Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const files: Array = []; + for (const entry of yield* fs.readDirectory(dir)) { + const entryPath = path.join(dir, entry); + const stat = yield* fs.stat(entryPath); + if (stat.type === "Directory") { + files.push(...(yield* collectSourceFiles(entryPath))); + } else if (/\.tsx?$/u.test(entry) && !/\.test\.tsx?$/u.test(entry)) { + files.push(entryPath); + } + } + return files; + }); +} + +describe("collectOldNameLiterals", () => { + const cases: ReadonlyArray = [ + ["a string literal", `const message = "Codex is disabled in T3 Code settings.";`, 1], + ["a template's static part", "const title = `T3 Code ${operation}`;", 1], + ["a template without substitutions", "const prompt = `you are running in T3 Code`;", 1], + ["JSX text", "const view =

Open T3 Code

;", 1], + ["a line comment", "// T3 Code's own OTLP variables name no signal", 0], + ["a block comment", "/** What T3 Code exports with. */\nconst x = 1;", 0], + ["a vendor identifier", `const clientInfo = { name: "t3code_desktop" };`, 0], + ["the product's own name", `const message = "Codex is disabled in settings.";`, 0], + ]; + for (const [name, source, expected] of cases) { + it(`${expected === 0 ? "ignores" : "reports"} ${name}`, () => { + assert.lengthOf(collectOldNameLiterals(source, "sample.tsx"), expected); + }); + } +}); + +it.effect("no server or shared-package literal names the product T3 Code", () => + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const root = yield* path.fromFileUrl(repoRootUrl); + const findings: Array = []; + for (const scanned of SCANNED_ROOTS) { + for (const file of yield* collectSourceFiles(path.join(root, scanned))) { + const relative = path.relative(root, file); + if (relative === VOCABULARY_TABLE) continue; + findings.push(...collectOldNameLiterals(yield* fs.readFileString(file), relative)); + } + } + assert.deepStrictEqual(findings, []); + }).pipe(Effect.provide(NodeServices.layer)), +);