Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
3421c1b
test(mobile): keep composer selection helper private (#9953)
juliusmarminge Sep 5, 2026
c21c6ee
test(contracts): keep driver default lookup private (#9968)
juliusmarminge Sep 5, 2026
6117e7a
refactor(mobile): remove unused layout calculations (#9974)
juliusmarminge Sep 5, 2026
569d13f
test(server): remove provider equality wrapper fixture (#9979)
juliusmarminge Sep 5, 2026
6db2317
test(server): assert the dispatched welcome thread model (#9980)
juliusmarminge Sep 5, 2026
9ec0e82
refactor(desktop): remove unused keyring remediation text (#9981)
juliusmarminge Sep 5, 2026
39d6fab
refactor(desktop): remove test-only Electron error predicates (#9982)
juliusmarminge Sep 5, 2026
0eb6ae7
test(server): remove authorization prompt snapshots (#9985)
juliusmarminge Sep 5, 2026
ac1a447
test(server): remove provider label identity assertion (#9987)
juliusmarminge Sep 5, 2026
e0d7da1
test(server): consolidate agent activity opt-in coverage (#9988)
juliusmarminge Sep 5, 2026
b77c440
refactor(shared): remove retired PATH capture parser (#9991)
juliusmarminge Sep 5, 2026
612921a
refactor(client-runtime): remove unused subagent selectors (#9992)
juliusmarminge Sep 5, 2026
af7e557
refactor(web): remove obsolete cloud listing helpers (#9995)
juliusmarminge Sep 5, 2026
854b404
test(server): cover raw OpenCode deltas through the adapter (#9977)
juliusmarminge Sep 5, 2026
d268469
refactor(server): remove test-only pricing normalizer (#10017)
juliusmarminge Sep 5, 2026
8be1a1f
refactor(web): test environment-scoped draft promotion (#10010)
juliusmarminge Sep 5, 2026
f1263d5
refactor(server): remove unused startup heartbeat launcher (#10030)
juliusmarminge Sep 5, 2026
611a03e
refactor(mobile): test composer persistence through the live decoder …
juliusmarminge Sep 5, 2026
0524c8b
refactor(web): remove unused sidebar selectors (#10034)
juliusmarminge Sep 5, 2026
ff10763
refactor(server): keep Cursor fallback models private (#10038)
juliusmarminge Sep 5, 2026
ad3dede
refactor(mobile): keep appearance calculations private (#10043)
juliusmarminge Sep 5, 2026
4f2e7c8
test(server): exercise Codex prompts through public assembly (#10045)
juliusmarminge Sep 5, 2026
6c8f8ed
refactor(shared): remove unused elapsed-time adapter (#10046)
juliusmarminge Sep 5, 2026
73185b8
refactor(web): remove obsolete HSL theme generator (#10061)
juliusmarminge Sep 5, 2026
c87d1b7
refactor(mobile): remove obsolete native diff token stream (#10062)
juliusmarminge Sep 5, 2026
def11a1
test(server): remove title prompt editorial snapshots (#10063)
juliusmarminge Sep 5, 2026
db513f1
refactor(web): observe preview tests through the live registry (#10064)
juliusmarminge Sep 5, 2026
63b5211
test(server): remove keybinding default assignment snapshot (#10065)
juliusmarminge Sep 5, 2026
2900b78
refactor(mobile): remove obsolete whole-file review highlighters (#10…
juliusmarminge Sep 5, 2026
1e61307
refactor(web): test live keybinding resolvers directly (#10069)
juliusmarminge Sep 5, 2026
24edb18
test(web): remove mocked diff view prop snapshot (#10073)
juliusmarminge Sep 5, 2026
eefbbb1
test(web): remove mocked annotation options snapshot (#10074)
juliusmarminge Sep 5, 2026
f62a837
refactor(mobile): remove unused cloud pending-status mapper (#10071)
juliusmarminge Sep 5, 2026
b7debcd
refactor(web): remove unused model picker hint helpers (#10072)
juliusmarminge Sep 5, 2026
44d95c5
test(web): drop provider banner styling assertions (#10148)
juliusmarminge Sep 5, 2026
ad97baf
refactor: preserve Pylon callers in upstream cleanup
rynfar Sep 6, 2026
ff7d2fe
test(server): cover Grok skill parsing through discovery (#10070)
juliusmarminge Sep 5, 2026
996867d
docs: record Grok cleanup adoption after workspace skills merge
rynfar Sep 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 60 additions & 6 deletions .agents/upstream-review.md

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion apps/desktop/src/electron/ElectronDialog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ describe("ElectronDialog", () => {
);

assert.instanceOf(error, ElectronDialog.ElectronDialogPickFolderError);
assert.isTrue(ElectronDialog.isElectronDialogError(error));
assert.strictEqual(error.ownerWindowId, 7);
assert.strictEqual(error.defaultPath, "/workspace");
assert.strictEqual(error.cause, cause);
Expand Down
1 change: 0 additions & 1 deletion apps/desktop/src/electron/ElectronDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ export const ElectronDialogError = Schema.Union([
ElectronDialogShowErrorBoxError,
]);
export type ElectronDialogError = typeof ElectronDialogError.Type;
export const isElectronDialogError = Schema.is(ElectronDialogError);

export interface ElectronDialogPickFolderInput {
readonly owner: Option.Option<Electron.BrowserWindow>;
Expand Down
1 change: 0 additions & 1 deletion apps/desktop/src/electron/ElectronTheme.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ describe("ElectronTheme", () => {
const error = yield* Effect.flip(electronTheme.setSource("dark"));

assert.instanceOf(error, ElectronTheme.ElectronThemeSetSourceError);
assert.isTrue(ElectronTheme.isElectronThemeSetSourceError(error));
assert.strictEqual(error.source, "dark");
assert.strictEqual(error.cause, cause);
assert.include(error.message, "dark");
Expand Down
2 changes: 0 additions & 2 deletions apps/desktop/src/electron/ElectronTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ export class ElectronThemeSetSourceError extends Schema.TaggedErrorClass<Electro
}
}

export const isElectronThemeSetSourceError = Schema.is(ElectronThemeSetSourceError);

export class ElectronTheme extends Context.Service<
ElectronTheme,
{
Expand Down
3 changes: 0 additions & 3 deletions apps/desktop/src/electron/ElectronUpdater.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ describe("ElectronUpdater", () => {
const error = yield* updater.checkForUpdates.pipe(Effect.flip);

assert.instanceOf(error, ElectronUpdater.ElectronUpdaterCheckForUpdatesError);
assert.isTrue(ElectronUpdater.isElectronUpdaterError(error));
assert.equal(error.channel, "beta");
assert.strictEqual(error.cause, cause);
assert.equal(error.message, "Electron updater failed to check for updates on channel beta.");
Expand All @@ -89,7 +88,6 @@ describe("ElectronUpdater", () => {
const error = yield* updater.downloadUpdate.pipe(Effect.flip);

assert.instanceOf(error, ElectronUpdater.ElectronUpdaterDownloadUpdateError);
assert.isTrue(ElectronUpdater.isElectronUpdaterError(error));
assert.equal(error.channel, "nightly");
assert.strictEqual(error.cause, cause);
assert.equal(
Expand Down Expand Up @@ -126,7 +124,6 @@ describe("ElectronUpdater", () => {
.pipe(Effect.flip);

assert.instanceOf(error, ElectronUpdater.ElectronUpdaterQuitAndInstallError);
assert.isTrue(ElectronUpdater.isElectronUpdaterError(error));
assert.equal(error.channel, "alpha");
assert.equal(error.isSilent, true);
assert.equal(error.isForceRunAfter, false);
Expand Down
1 change: 0 additions & 1 deletion apps/desktop/src/electron/ElectronUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ export const ElectronUpdaterError = Schema.Union([
ElectronUpdaterQuitAndInstallError,
]);
export type ElectronUpdaterError = typeof ElectronUpdaterError.Type;
export const isElectronUpdaterError = Schema.is(ElectronUpdaterError);

export class ElectronUpdater extends Context.Service<
ElectronUpdater,
Expand Down
1 change: 0 additions & 1 deletion apps/desktop/src/electron/ElectronWindow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ describe("ElectronWindow", () => {
const error = yield* electronWindow.create(options).pipe(Effect.flip);

assert.instanceOf(error, ElectronWindow.ElectronWindowCreateError);
assert.isTrue(ElectronWindow.isElectronWindowCreateError(error));
assert.deepEqual(error.options, {
title: "Pylon",
width: 1100,
Expand Down
2 changes: 0 additions & 2 deletions apps/desktop/src/electron/ElectronWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ export class ElectronWindowCreateError extends Schema.TaggedErrorClass<ElectronW
}
}

export const isElectronWindowCreateError = Schema.is(ElectronWindowCreateError);

export class ElectronWindowOperationError extends Schema.TaggedErrorClass<ElectronWindowOperationError>()(
"ElectronWindowOperationError",
{
Expand Down
77 changes: 0 additions & 77 deletions apps/desktop/src/linuxSecretStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { describe, expect, it } from "vite-plus/test";
import {
normalizeLinuxPasswordStorePreference,
resolveLinuxPasswordStoreSwitch,
resolveLinuxSecretStorageUnavailableMessage,
} from "./linuxSecretStorage.ts";

const autoSwitch = (env: NodeJS.ProcessEnv) =>
Expand Down Expand Up @@ -124,80 +123,4 @@ describe("linuxSecretStorage", () => {
}),
).toBe("gnome-libsecret");
});

it("uses GNOME Keyring remediation for libsecret and unknown backends", () => {
expect(
resolveLinuxSecretStorageUnavailableMessage({
configuredPreference: "auto",
selectedBackend: "gnome_libsecret",
env: { XDG_CURRENT_DESKTOP: "niri" },
}),
).toContain("GNOME Keyring");
});

it("prefers explicit libsecret selection over KDE desktop heuristics", () => {
expect(
resolveLinuxSecretStorageUnavailableMessage({
configuredPreference: "gnome-libsecret",
selectedBackend: "unknown",
env: { XDG_CURRENT_DESKTOP: "KDE" },
}),
).toContain("GNOME Keyring");
expect(
resolveLinuxSecretStorageUnavailableMessage({
configuredPreference: "auto",
selectedBackend: "gnome_libsecret",
env: { XDG_CURRENT_DESKTOP: "KDE" },
}),
).toContain("GNOME Keyring");
});

it("prefers explicit KWallet preference over selected gnome-libsecret backend", () => {
expect(
resolveLinuxSecretStorageUnavailableMessage({
configuredPreference: "kwallet6",
selectedBackend: "gnome_libsecret",
env: { XDG_CURRENT_DESKTOP: "niri" },
}),
).toContain("KWallet");
expect(
resolveLinuxSecretStorageUnavailableMessage({
configuredPreference: "kwallet",
selectedBackend: "gnome-libsecret",
env: {},
}),
).toContain("KWallet");
});

it("uses KWallet remediation wording for KDE-looking sessions", () => {
expect(
resolveLinuxSecretStorageUnavailableMessage({
configuredPreference: "auto",
selectedBackend: "kwallet6",
env: {},
}),
).toContain("KWallet");
expect(
resolveLinuxSecretStorageUnavailableMessage({
configuredPreference: "auto",
selectedBackend: "unknown",
env: { XDG_CURRENT_DESKTOP: "KDE" },
}),
).toContain("KWallet");
expect(
resolveLinuxSecretStorageUnavailableMessage({
configuredPreference: "auto",
selectedBackend: "unknown",
env: { DESKTOP_SESSION: "plasmawayland" },
}),
).toContain("KWallet");
// A desktop name outranks a bare KDE marker when choosing the wording.
expect(
resolveLinuxSecretStorageUnavailableMessage({
configuredPreference: "auto",
selectedBackend: "unknown",
env: { GDMSESSION: "gnome", KDE_FULL_SESSION: "true" },
}),
).toContain("GNOME Keyring");
});
});
99 changes: 0 additions & 99 deletions apps/desktop/src/linuxSecretStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ const ELECTRON_KDE_DESKTOP = "KDE";
// Chromium recognizes LXQt and still selects basic text for it, so it does need a forced backend.
const ELECTRON_UNPROTECTED_DESKTOPS = new Set(["LXQt"]);

const KDE_NAME_PREFIXES = ["kde", "plasma"];
const NEGATIVE_FLAG_VALUES = new Set(["0", "false", "no", "off"]);

export function normalizeLinuxPasswordStorePreference(
value: unknown,
): LinuxPasswordStorePreference {
Expand Down Expand Up @@ -77,102 +74,6 @@ function electronSelectsProtectedBackend(env: NodeJS.ProcessEnv): boolean {
return false;
}

export function resolveLinuxSecretStorageUnavailableMessage(input: {
readonly configuredPreference: LinuxPasswordStorePreference;
readonly selectedBackend: string | null;
readonly env: NodeJS.ProcessEnv;
}): string {
if (input.configuredPreference === "gnome-libsecret") {
return getGnomeKeyringRemediationMessage();
}

if (
input.configuredPreference === "kwallet" ||
input.configuredPreference === "kwallet5" ||
input.configuredPreference === "kwallet6"
) {
return getKWalletRemediationMessage();
}

const backend = normalizeSelectedStorageBackend(input.selectedBackend);
if (backend === "gnome-libsecret") {
return getGnomeKeyringRemediationMessage();
}

if (
backend === "kwallet" ||
backend === "kwallet5" ||
backend === "kwallet6" ||
looksLikeKdeSession(input.env)
) {
return getKWalletRemediationMessage();
}

return getGnomeKeyringRemediationMessage();
}

function getGnomeKeyringRemediationMessage(): string {
return "Pylon could not access GNOME Keyring to save this environment credential. Install and start GNOME Keyring, then restart Pylon.";
}

function getKWalletRemediationMessage(): string {
return "Pylon could not access KWallet to save this environment credential. Enable the KDE wallet subsystem in System Settings, then restart Pylon.";
}

// Advisory only: this picks between the GNOME Keyring and KWallet wording in the failure notice. It
// never decides which backend to select, so a loose match costs a user slightly wrong instructions
// rather than an unprotected credential store.
function looksLikeKdeSession(env: NodeJS.ProcessEnv): boolean {
const currentDesktopNames = nonEmptyDesktopNames(env.XDG_CURRENT_DESKTOP);
if (currentDesktopNames.length > 0) {
return currentDesktopNames.some(isKdeDesktopName);
}

const legacyNames = legacyDesktopNames(env);
if (legacyNames.length > 0) {
return legacyNames.some(isKdeDesktopName);
}

return isSet(env.KDE_SESSION_VERSION) || isAffirmativeFlag(env.KDE_FULL_SESSION);
}

function isKdeDesktopName(name: string): boolean {
return KDE_NAME_PREFIXES.some((prefix) => name.startsWith(prefix));
}

function legacyDesktopNames(env: NodeJS.ProcessEnv): string[] {
return [env.XDG_SESSION_DESKTOP, env.DESKTOP_SESSION, env.GDMSESSION].flatMap((entry) => {
const normalized = normalizeDesktopName(entry);
return normalized ? [normalized] : [];
});
}

function nonEmptyDesktopNames(value: string | undefined): string[] {
return splitDesktopNameList(value).flatMap((entry) => {
const normalized = normalizeDesktopName(entry);
return normalized ? [normalized] : [];
});
}

function isSet(value: string | undefined): boolean {
return Boolean(value?.trim());
}

function isAffirmativeFlag(value: string | undefined): boolean {
const normalized = value?.trim().toLowerCase();
return normalized ? !NEGATIVE_FLAG_VALUES.has(normalized) : false;
}

function splitDesktopNameList(value: string | undefined): string[] {
return value?.split(":") ?? [];
}

function normalizeDesktopName(value: string | undefined): string | null {
const normalized = value?.trim().toLowerCase();
return normalized && normalized.length > 0 ? normalized : null;
}

function normalizeSelectedStorageBackend(value: string | null): string | null {
const normalized = value?.trim().toLowerCase().replace(/_/gu, "-");
return normalized && normalized.length > 0 ? normalized : null;
}
11 changes: 0 additions & 11 deletions apps/mobile/src/features/cloud/linkEnvironment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { MobilePreferencesStore } from "../../persistence/mobile-preferences";
import { MobileStorage } from "../../persistence/mobile-storage";

import {
cloudEnvironmentsPendingStatus,
linkEnvironmentToCloud,
linkEnvironmentToCloudWithPreference,
connectCloudEnvironment,
Expand Down Expand Up @@ -186,16 +185,6 @@ describe("mobile cloud link environment client", () => {
loadPreferences.mockClear();
});

it("makes linked environments visible while their status is still loading", () => {
expect(cloudEnvironmentsPendingStatus([listedEnvironment("env-1")])).toMatchObject([
{
environment: { environmentId: "env-1", label: "Desktop" },
status: null,
statusError: "Checking status...",
},
]);
});

it.effect("decodes relay environment list responses before returning records", () =>
Effect.gen(function* () {
vi.stubGlobal(
Expand Down
10 changes: 0 additions & 10 deletions apps/mobile/src/features/cloud/linkEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,16 +397,6 @@ export function getCloudEnvironmentStatus(input: {
});
}

export function cloudEnvironmentsPendingStatus(
environments: ReadonlyArray<RelayClientEnvironmentRecord>,
): ReadonlyArray<CloudEnvironmentRecordWithStatus> {
return environments.map((environment) => ({
environment,
status: null,
statusError: "Checking status...",
}));
}

export function loadCloudEnvironmentStatuses(input: {
readonly clerkToken: string;
readonly environments: ReadonlyArray<RelayClientEnvironmentRecord>;
Expand Down
Loading
Loading