test: remove shallow catalog, browser and launch checks (#41258)

* test: remove routine native and catalog suites

* test: remove shallow browser, bridge and CLI checks

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
OrcaWin
2026-11-11 14:44:15 -08:00
committed by GitHub
co-authored by OrcaWin
parent 057f5772e9
commit a9a0e8cd21
18 changed files with 5 additions and 944 deletions
@@ -4471,7 +4471,6 @@
"src/renderer/src/components/dashboard/agent-destination-navigation.integration.test.tsx": 3232,
"src/renderer/src/components/dashboard/agent-row-lineage-model.test.ts": 107,
"src/renderer/src/components/dashboard/build-dashboard-bucket-counts.equivalence.test.ts": 722,
"src/renderer/src/components/dashboard/build-dashboard-snapshot-folder-workspace.test.ts": 2150,
"src/renderer/src/components/dashboard/build-dashboard-snapshot.test.ts": 2121,
"src/renderer/src/components/dashboard/reveal-dashboard-agent.test.ts": 1098,
"src/renderer/src/components/dashboard/useRetainedAgents.test.ts": 2028,
@@ -4710,7 +4709,6 @@
"src/renderer/src/components/github-project/group-sort.test.ts": 75,
"src/renderer/src/components/github-project/project-dialog-state.test.ts": 48,
"src/renderer/src/components/github-project/project-picker-input.test.ts": 338,
"src/renderer/src/components/github-project/project-row-filtering.test.ts": 65,
"src/renderer/src/components/github-project/project-view-wrapper-source-context-boundary.test.ts": 46,
"src/renderer/src/components/github/GitHubMarkdownComposer.test.tsx": 1571,
"src/renderer/src/components/github/PRFilterPickers.test.ts": 291,
@@ -1,68 +0,0 @@
package expo.modules.orcamobilewebshell
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
private const val FOREIGN = "https://example.com/artifact-link"
private const val DOCUMENT = "orca-mobile-web://sess-01JN_aZ9/"
private fun verdict(
url: String? = FOREIGN,
isForMainFrame: Boolean = true,
isDocumentUrl: Boolean = false,
hasGesture: Boolean = true
) = mobileWebShellNavigationVerdict(
url,
isForMainFrame,
false,
isDocumentUrl,
false,
hasGesture,
false
)
class MobileWebShellDroppedNavigationTest {
@Test
fun `refuses every navigation to the document that the shell did not ask for`() {
// Artifact href=/ or empty href names our document; never reload or send that URL to the opener.
assertEquals(
MobileWebShellNavigationVerdict.Cancel,
verdict(url = DOCUMENT, isDocumentUrl = true)
)
// Both engines can report no gesture for subframe top navigation; Chromium permits it for human requests too.
assertEquals(
MobileWebShellNavigationVerdict.Cancel,
verdict(url = DOCUMENT, isDocumentUrl = true, hasGesture = false)
)
}
@Test
fun `cancels a foreign navigation with no gesture and offers nothing`() {
// Meta refresh/redirects must not open a browser without a user action.
assertEquals(MobileWebShellNavigationVerdict.Cancel, verdict(hasGesture = false))
}
@Test
fun `offers nothing for a subframe, which is the sealed preview loading itself`() {
assertEquals(MobileWebShellNavigationVerdict.Cancel, verdict(isForMainFrame = false))
assertEquals(
MobileWebShellNavigationVerdict.Cancel,
verdict(isForMainFrame = false, hasGesture = false)
)
}
@Test
fun `offers nothing for an absent or empty url, and nothing past the crossing cap`() {
assertEquals(MobileWebShellNavigationVerdict.Cancel, verdict(url = null))
assertEquals(MobileWebShellNavigationVerdict.Cancel, verdict(url = ""))
val cap = MOBILE_WEB_SHELL_MAX_DROPPED_NAVIGATION_URL_CHARS
val atCap = "https://example.com/" + "a".repeat(cap - "https://example.com/".length)
assertEquals(cap, atCap.length)
assertEquals(atCap, mobileWebShellOfferableUrl(atCap))
assertNull(mobileWebShellOfferableUrl(atCap + "a"))
assertEquals(MobileWebShellNavigationVerdict.Cancel, verdict(url = atCap + "a"))
}
}
@@ -3,7 +3,6 @@ package expo.modules.orcamobilewebshell
import java.io.File
import org.json.JSONArray
import org.json.JSONObject
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Test
@@ -30,23 +29,6 @@ private fun manifest(
private fun make(json: String) = MobileWebShellGeneration.make(json, DIRECTORY)
class MobileWebShellGenerationTest {
@Test
fun `maps the document, every declared asset and the manifest itself`() {
val generation = make(manifest())
assertNotNull(generation)
val entries = generation!!.entries
assertEquals(4, entries.size)
assertEquals(File(DIRECTORY, "index.html"), entries["/"]!!.file)
assertEquals("text/html; charset=utf-8", entries["/"]!!.contentType)
// Only / may serve document bytes with CSP; no entrypoint alias.
assertNull(entries["/index.html"])
assertEquals(File(DIRECTORY, "assets/bb.png"), entries["/assets/bb.png"]!!.file)
assertEquals("image/png", entries["/assets/bb.png"]!!.contentType)
// The manifest is written last and is not part of the content hash, so it is not in assets[].
assertEquals("application/json", entries["/manifest.json"]!!.contentType)
assertNull(entries["/assets/cc.js"])
}
@Test
fun `refuses a manifest whose shape it does not recognise`() {
assertNull(make("not json"))
@@ -35,11 +35,6 @@ private fun resolve(request: MobileWebShellRequestParts): String? =
class MobileWebShellOriginTest {
@Test
fun `binds a host the parser canonicalised`() {
assertEquals("/", resolve(parts("/", host = mobileWebShellOriginHost(SESSION)!!.uppercase())))
}
@Test
fun `refuses everything outside a plain GET on this origin`() {
assertNull(resolve(parts("/", method = "POST")))
@@ -50,29 +50,6 @@ describe('init and state', () => {
params: { paneKey: 'pane-1' }
})
})
it('reads the keys again for each init, rather than replaying what it started with', () => {
let pins = '["one"]'
const bridge = harness({
readStorage: () => ({ storage: { 'orca:pins:host-a': pins }, storageOversize: [] })
})
bridge.host.receive(clientFrame({ type: 'ready' }))
pins = '["one","two"]'
// Reloaded documents must see writes made since mount in their new init.
bridge.host.receive(clientFrame({ type: 'ready' }))
const inits = bridge.frames().filter((frame) => frame.type === 'init')
expect(inits.map((frame) => (frame.type === 'init' ? frame.storage : null))).toEqual([
{ 'orca:pins:host-a': '["one"]' },
{ 'orca:pins:host-a': '["one","two"]' }
])
})
it('pushes the event state, not the getter a listener can outrun', () => {
const bridge = harness()
bridge.client.pushState('disconnected')
const pushed = bridge.last()
expect(pushed.type === 'state' && pushed.connection.state).toBe('disconnected')
})
it('sends a page that reads them a path frame when a relay dial starts without a state change', () => {
let pendingPath: 'relay' | null = null
let notifyPath = () => {}
-13
View File
@@ -121,19 +121,6 @@ describe('chat send', () => {
})
})
it('reports a host refusal as an error instead of a sent message', async () => {
const client = fakeClient([
workState({ fence: 2 }),
ok({
ok: false,
refusal: { code: 'agent_session_fence_mismatch', message: 'The chat restarted.' }
})
])
await expect(run('chat send', { session: SESSION, text: 'hi' }, client)).rejects.toMatchObject({
code: 'agent_session_fence_mismatch'
})
})
it('with --wait, waits for its queued message to run and returns that turn', async () => {
vi.useFakeTimers()
const client = fakeClient([
@@ -32,22 +32,6 @@ describe('native account verification before agy launch', () => {
vi.spyOn(process, 'platform', 'get').mockReturnValue('darwin')
})
it('retains non-Windows delegation and propagates native mismatch refusal', async () => {
prepareForLaunch.mockRejectedValueOnce(new Error('native account changed'))
await expect(
prepareAntigravityAccountForLaunch({
command: 'agy',
env: { HOME: '/task/home' },
envIsComplete: true
})
).rejects.toThrow('native account changed')
await prepareAntigravityAccountForLaunch({
command: 'agy',
env: { HOME: '/task/home' },
envIsComplete: true
})
expect(prepareForLaunch).toHaveBeenCalledTimes(2)
})
it('preserves owning-host and distro boundaries without reading client credentials', async () => {
await prepareAntigravityAccountForLaunch({
launchAgent: 'antigravity',
@@ -215,31 +215,6 @@ describe.each(['renderer', 'runtime'])('%s managed account daemon environment',
}
})
it('preserves independent daemon defaults when main has no baseline or owned markers', async () => {
const env: Record<string, string> = {}
applyManagedDataAccountEnvironment(env, { launchAgent: 'opencode' })
const envToDelete = await spawnDeletions(route, env)
const defaults = {
XDG_DATA_HOME: join(tmpdir(), 'persistent-daemon', 'data'),
XDG_STATE_HOME: join(tmpdir(), 'persistent-daemon', 'state'),
OPENCODE_DB: 'daemon.db',
OPENCODE_AUTH_CONTENT: JSON.stringify({ fixture: { key: randomUUID() } })
}
for (const [key, value] of Object.entries(defaults)) {
vi.stubEnv(key, value)
}
const child = createDaemonPtyEnvironment({
sessionId: 'pane',
cols: 80,
rows: 24,
env,
envToDelete
})
for (const [key, value] of Object.entries(defaults)) {
expect(hash(child[key]) === hash(value)).toBe(true)
}
})
it('keeps inline System authentication out of every selected child marker', async () => {
const secret = randomUUID()
const baseline = JSON.stringify({ fixture: { key: secret } })
-80
View File
@@ -1,26 +1,7 @@
import { describe, it, expect } from 'vitest'
import { redactString, redactValue } from './redactor'
const SECRETS = {
anthropic: 'sk-ant-api03-aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789ABCDEFGHIJKLMNOP',
github: 'ghp_AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AB'
}
describe('redactor — labeled key-value', () => {
it('redacts api_key:', () => {
expect(redactString('api_key: hunter2')).toBe('[redacted:labeled-kv]')
})
it('redacts Authorization=Bearer …', () => {
expect(redactString('Authorization=Bearer abcdef')).toBe('[redacted:labeled-kv]')
})
it('preserves surrounding context outside the matched segment', () => {
const out = redactString('before api_key=xyz after')
expect(out).toContain('before')
expect(out).toContain('after')
expect(out).not.toContain('xyz')
})
it.each([
{
name: 'compound OAuth names and ordinary quoted escapes',
@@ -57,15 +38,6 @@ describe('redactor — labeled key-value', () => {
})
})
describe('redactor — URL userinfo strip', () => {
it('strips user:pass@ from https URLs', () => {
const out = redactString('clone failed: https://ghp_xxxxxxxxxx@github.com/foo/bar')
expect(out).not.toContain('ghp_xxxxxxxxxx@')
expect(out).toContain('github.com/foo/bar')
expect(out).toContain('[redacted]@')
})
})
describe('redactor — complete credential spans', () => {
it.each([
{
@@ -112,17 +84,6 @@ describe('redactor — complete credential spans', () => {
})
})
describe('redactor — .env-shape line', () => {
it('handles multi-line .env dumps', () => {
const out = redactString(['DB_HOST=db.local', 'DB_PASSWORD=hunter2', '# comment'].join('\n'))
expect(out).toContain('DB_HOST=[redacted:env-value]')
expect(out).toContain('DB_PASSWORD=[redacted:env-value]')
expect(out).toContain('# comment')
expect(out).not.toContain('hunter2')
expect(out).not.toContain('db.local')
})
})
describe('redactor — attribute-key blocklist', () => {
it('drops compound structured secret-bearing keys with plain values', () => {
const out = redactValue({
@@ -154,45 +115,4 @@ describe('redactor — attribute-key blocklist', () => {
expect(out).not.toHaveProperty('serverSecretKey')
expect(out.keep).toBe('ok')
})
it('drops nested blocked keys while recursively redacting values', () => {
const out = redactValue({
request: {
headers: {
authorization: 'Bearer plain-secret',
cookie: 'sid=plain-secret',
keep: 'ok'
}
}
}) as { request: { headers: Record<string, unknown> } }
expect(out.request.headers).not.toHaveProperty('authorization')
expect(out.request.headers).not.toHaveProperty('cookie')
expect(out.request.headers.keep).toBe('ok')
})
})
describe('redactor — server mode adds install_id keys', () => {
it('drops identity keys nested inside server-mode values', () => {
const out = redactValue({ context: { install_id: 'abc', keep: 'me' } }, 'server') as {
context: Record<string, unknown>
}
expect(out.context).not.toHaveProperty('install_id')
expect(out.context.keep).toBe('me')
})
})
describe('redactor — recursive value redaction', () => {
it('recurses into nested objects', () => {
const out = redactValue({ outer: { inner: `key: ${SECRETS.anthropic}` } }) as Record<
string,
Record<string, string>
>
expect(out.outer.inner).not.toContain(SECRETS.anthropic)
expect(out.outer.inner).toContain('[redacted:anthropic-key]')
})
it('recurses into arrays', () => {
const out = redactValue([SECRETS.github, 'plain']) as string[]
expect(out[0]).not.toContain(SECRETS.github)
expect(out[1]).toBe('plain')
})
})
@@ -81,17 +81,4 @@ describe('UsageWorktreeHistory', () => {
await history.flush()
expect(readFileSync(file, 'utf8')).toBe(newer)
})
it('lets a live worktree in another repo own a path a removed one used', () => {
const other: Repo = { ...repo, id: 'repo-2', path: '/src/other' }
const source: UsageWorktreeSource = {
getRepos: () => [repo, other],
getAllWorktreeMeta: () => ({ 'repo-2::/ws/feat': { displayName: 'live' } }),
getRememberedWorktreeDisplayNames: () => new Map([['repo-1::/ws/feat', 'removed']]),
whenLoaded: async () => {}
}
const known = loadKnownUsageWorktreesByRepo(source, [repo, other])
expect(known.get('repo-1')?.map(({ path }) => path)).toEqual(['/src/app'])
expect(known.get('repo-2')?.map(({ path }) => path)).toEqual(['/src/other', '/ws/feat'])
})
})
@@ -5,19 +5,14 @@ import { getDefaultSettings } from '../../../../../shared/constants'
import { resetHostModelCatalogSnapshotsForTests } from '@/runtime/native-chat/model-catalogs/host-model-catalog-snapshots'
import { useAppStore } from '@/store'
import { TooltipProvider } from '../../ui/tooltip'
import type { RuntimeClientTarget } from '../../../../../shared/runtime-client-target'
import { AgentLaunchChoiceEditor } from './AgentLaunchChoiceEditor'
const call = vi.hoisted(() => vi.fn())
const discover = vi.hoisted(() => vi.fn())
const menus = vi.hoisted(() => new Map<string, string[]>())
vi.mock('@/runtime/native-chat/requests/structured-agent-session-call', () => ({
callStructuredAgentSession: call
}))
vi.mock('@/runtime/source-control/git/runtime-git-generation-client', () => ({
discoverRuntimeCommitMessageModels: discover
}))
vi.mock('./AgentChoiceMenu', () => ({
AgentChoiceMenu: ({
label,
@@ -54,20 +49,16 @@ const LISTED = {
const HOST = { kind: 'environment', environmentId: 'env-1' } as const
function renderEditor(
model?: string,
agent: 'codex' | 'cursor' = 'codex',
catalogTarget: RuntimeClientTarget = HOST
): void {
function renderEditor(): void {
render(
<TooltipProvider>
<AgentLaunchChoiceEditor
agent={agent}
label={agent}
choices={model ? { model } : undefined}
agent="codex"
label="codex"
choices={undefined}
userArgs=""
permission={undefined}
catalogTarget={catalogTarget}
catalogTarget={HOST}
save={async () => {}}
/>
</TooltipProvider>
@@ -79,7 +70,6 @@ describe('AgentLaunchChoiceEditor model list', () => {
beforeEach(() => {
call.mockReset()
discover.mockReset()
menus.clear()
resetHostModelCatalogSnapshotsForTests()
})
@@ -109,20 +99,4 @@ describe('AgentLaunchChoiceEditor model list', () => {
await act(async () => answerOlder(LISTED))
expect(menus.get('Model')).toEqual(['__agent_default__', 'gpt-wrapped'])
})
it("lists the local Cursor CLI's models", async () => {
// The host's structured catalog has no Cursor listing; Settings must not settle for it.
call.mockResolvedValue({ origin: 'unknown' })
discover.mockResolvedValueOnce({
success: true,
catalogOrigin: 'probe',
models: [
{ id: 'auto', label: 'Auto', isDefault: true },
{ id: 'claude-opus-5-5-max', label: 'Claude Opus 5.5 Max' }
]
})
useAppStore.setState({ settings: getDefaultSettings('') })
renderEditor(undefined, 'cursor', { kind: 'local' })
await waitFor(() => expect(menus.get('Model')).toContain('claude-opus-5-5-max'))
})
})
@@ -265,73 +265,6 @@ describe('ClientHostedBrowserPagePane', () => {
expect.objectContaining({ loading: false, loadError: null })
)
})
it('offers Reopen without a stale load-failure surface until the restored page attaches', () => {
mocks.restoredPageUnrecovered = true
const browserTab = {
...page(),
url: 'https://remote.internal/failed',
loadError: {
code: -120,
description: 'ERR_SOCKS_CONNECTION_FAILED',
validatedUrl: 'https://remote.internal/failed'
}
}
const pane = (placement: typeof PLACEMENT | null) => (
<ClientHostedBrowserPagePane
browserTab={browserTab}
workspaceId="workspace-a"
chromeShortcutScope="focused"
runtimeEnvironmentId="environment-a"
worktreeId="worktree-a"
placement={placement}
isActive
onUpdatePageState={vi.fn()}
onSetUrl={vi.fn()}
/>
)
const view = render(pane(null))
expect(
screen.getByRole<HTMLButtonElement>('button', { name: 'Reopen on server' }).disabled
).toBe(false)
expect(screen.queryByText('Retry', { selector: 'button' })).toBeNull()
const { webview, setUrl } = createWebview()
setUrl(browserTab.url)
mocks.attach.mockReturnValue(retainedAttachment(webview))
mocks.restoredPageUnrecovered = false
view.rerender(pane(PLACEMENT))
expect(screen.queryByRole('button', { name: 'Reopen on server' })).toBeNull()
expect(screen.getByText('Retry', { selector: 'button' })).toBeTruthy()
})
it('shows exact-generation unavailability without creating a fallback guest', () => {
mocks.attach.mockReturnValue(null)
render(
<ClientHostedBrowserPagePane
browserTab={page()}
workspaceId="workspace-a"
chromeShortcutScope="focused"
runtimeEnvironmentId="environment-a"
worktreeId="worktree-a"
placement={{ ...PLACEMENT, pageHostGeneration: 8 }}
isActive
onUpdatePageState={vi.fn()}
onSetUrl={vi.fn()}
/>
)
expect(mocks.attach).toHaveBeenCalledTimes(1)
expect(mocks.attach).toHaveBeenCalledWith(
{ browserPageId: 'page-a', pageHostGeneration: 8 },
expect.any(HTMLElement)
)
expect(screen.getByText('Client-hosted browser unavailable')).not.toBeNull()
expect(document.querySelector('webview')).toBeNull()
})
})
describe('ClientHostedBrowserPagePane address bar parity', () => {
@@ -1,144 +0,0 @@
import { describe, expect, it } from 'vitest'
import { makePaneKey } from '../../../../shared/workspace-layout/stable-pane-id'
import { folderWorkspaceKey } from '../../../../shared/workspace-scope'
import type { FolderWorkspace } from '../../../../shared/folder-workspaces/folder-workspace-types'
import type { ProjectGroup } from '../../../../shared/project-group-types'
import type { Tab } from '../../../../shared/tab-types'
import type { TerminalTab } from '../../../../shared/workspace-layout/terminal-tab-types'
import type { AgentStatusEntry } from '../../../../shared/agent-status/contracts/agent-status-types'
import {
buildDashboardSnapshot,
type DashboardSnapshotInput as DashboardSnapshotState
} from './build-dashboard-snapshot'
const NOW = 2_000_000_000
const WORKSPACE_ID = folderWorkspaceKey('folder-1')
const TAB_ID = 'folder-tab'
const LEAF_ID = '11111111-1111-4111-8111-111111111111'
const PANE_KEY = makePaneKey(TAB_ID, LEAF_ID)
function folderWorkspace(): FolderWorkspace {
return {
id: 'folder-1',
projectGroupId: 'group-1',
name: 'Docs workspace',
folderPath: '/workspace/docs',
connectionId: 'ssh-1',
linkedTask: null,
comment: '',
isArchived: false,
isUnread: false,
isPinned: false,
sortOrder: 0,
lastActivityAt: NOW,
createdAt: NOW,
updatedAt: NOW
}
}
function projectGroup(): ProjectGroup {
return {
id: 'group-1',
name: 'Documentation',
parentPath: '/workspace',
connectionId: 'ssh-1',
parentGroupId: null,
createdFrom: 'folder-scan',
tabOrder: 0,
isCollapsed: false,
color: null,
createdAt: NOW,
updatedAt: NOW
}
}
function tab(): TerminalTab {
return {
id: TAB_ID,
ptyId: 'pty-folder',
worktreeId: WORKSPACE_ID,
title: 'codex',
customTitle: 'Docs reviewer',
color: null,
sortOrder: 0,
createdAt: NOW
}
}
function entry(): AgentStatusEntry {
return {
paneKey: PANE_KEY,
state: 'working',
prompt: 'Review the docs',
updatedAt: NOW,
stateStartedAt: NOW - 60_000,
stateHistory: [],
agentType: 'codex',
tabId: TAB_ID,
worktreeId: WORKSPACE_ID
}
}
function state(): DashboardSnapshotState {
return {
chatNames: new Map(),
repos: [],
worktreesByRepo: {},
folderWorkspaces: [folderWorkspace()],
projectGroups: [projectGroup()],
tabsByWorktree: { [WORKSPACE_ID]: [tab()] },
agentStatusByPaneKey: { [PANE_KEY]: entry() },
retainedAgentsByPaneKey: {},
migrationUnsupportedByPtyId: {},
runtimeAgentOrchestrationByPaneKey: {},
terminalLayoutsByTabId: {
[TAB_ID]: {
root: { type: 'leaf', leafId: LEAF_ID },
activeLeafId: LEAF_ID,
expandedLeafId: null,
ptyIdsByLeafId: { [LEAF_ID]: 'pty-folder' }
}
},
ptyIdsByTabId: { [TAB_ID]: ['pty-folder'] },
runtimePaneTitlesByTabId: {},
acknowledgedAgentsByPaneKey: {},
settings: null
}
}
describe('buildDashboardSnapshot folder workspaces', () => {
it('keeps done structured sessions visible when their tab exists only in unified tabs', () => {
const structuredState = state()
structuredState.tabsByWorktree = { [WORKSPACE_ID]: [] }
structuredState.unifiedTabsByWorktree = {
[WORKSPACE_ID]: [
{
id: TAB_ID,
entityId: 'session-1',
groupId: 'group-1',
worktreeId: WORKSPACE_ID,
contentType: 'agent-session',
label: 'Codex Chat',
customLabel: null,
color: null,
sortOrder: 0,
createdAt: NOW,
isPinned: false,
agentSessionAgent: 'codex'
} satisfies Tab
]
}
structuredState.agentStatusByPaneKey = {
[PANE_KEY]: {
...entry(),
state: 'done',
sessionBoundary: true
}
}
const snapshot = buildDashboardSnapshot(structuredState, NOW)
expect(snapshot.cards).toHaveLength(1)
expect(snapshot.cards[0]).toMatchObject({ paneKey: PANE_KEY, bucket: 'done' })
})
})
@@ -1,125 +0,0 @@
import { describe, expect, it, vi } from 'vitest'
import type { GitHubProjectRow, GitHubProjectTable } from '../../../../shared/github/project-types'
import type { Repo } from '../../../../shared/repo-types'
import { filterProjectTableRowsBySelectedRepos } from './project-row-filtering'
function repo(id: string): Repo {
return {
id,
path: `/repos/${id}`,
displayName: id,
badgeColor: '#000',
addedAt: 1
}
}
function originOnly(matches: Repo[]): { origin: Repo[]; upstream: Repo[] } {
return { origin: matches, upstream: [] }
}
function row(id: string, repository: string | null): GitHubProjectRow {
return {
id,
itemType: 'ISSUE',
content: {
number: 1,
title: id,
body: null,
url: null,
state: 'OPEN',
stateReason: null,
isDraft: null,
repository,
assignees: [],
labels: [],
parentIssue: null,
issueType: null
},
fieldValuesByFieldId: {},
updatedAt: '2026-01-01T00:00:00Z',
position: 0
}
}
function table(rows: GitHubProjectRow[]): GitHubProjectTable {
return {
project: {
id: 'P',
owner: 'acme',
ownerType: 'organization',
number: 1,
title: 'Project',
url: 'https://github.com/orgs/acme/projects/1'
},
selectedView: {
id: 'V',
number: 1,
name: 'Default',
layout: 'TABLE_LAYOUT',
filter: '',
fields: [],
groupByFields: [],
sortByFields: []
},
rows,
totalCount: rows.length,
parentFieldDropped: false
}
}
describe('filterProjectTableRowsBySelectedRepos', () => {
it('keeps draft items and inaccessible content while scoping repository-backed items', () => {
// Normalized shapes: drafts and restricted items carry no repository or number.
const drafts = Array.from({ length: 1 }, (_, position): GitHubProjectRow => {
const base = row(`draft-${position}`, null)
return {
...base,
itemType: 'DRAFT_ISSUE',
content: { ...base.content, number: null, state: null, body: 'Draft body' },
fieldValuesByFieldId: {
status: {
kind: 'single-select',
fieldId: 'status',
optionId: 'todo',
name: 'Todo',
color: 'GRAY'
}
},
position
}
})
const draftTable = table(drafts)
const lookup = vi.fn(() => originOnly([]))
expect(filterProjectTableRowsBySelectedRepos(draftTable, lookup, true, new Set())).toBe(
draftTable
)
expect(lookup).not.toHaveBeenCalled()
const restricted = ['ISSUE', 'PULL_REQUEST'].map((type): GitHubProjectRow => {
const base = row(`restricted-${type}`, null)
return {
...base,
itemType: 'REDACTED',
content: { ...base.content, title: 'Restricted item', number: null, state: null }
}
})
const issue = row('issue', 'acme/orca')
const pullRequest: GitHubProjectRow = { ...row('pr', 'acme/orca'), itemType: 'PULL_REQUEST' }
const filtered = filterProjectTableRowsBySelectedRepos(
table([
...drafts,
...restricted,
issue,
pullRequest,
row('unselected', 'acme/other'),
// An older host sends inaccessible Issue/PR content as a blank Issue row.
row('old-host-blank-issue', null)
]),
(slug) => originOnly([repo(slug === 'acme/orca' ? 'selected' : 'other')]),
true,
new Set(['selected'])
)
expect(filtered.rows).toEqual([...drafts, ...restricted, issue, pullRequest])
expect(filtered.totalCount).toBe(5)
})
})
@@ -1,38 +0,0 @@
import { expect, it } from 'vitest'
import { agentPickerEntryOptions } from './agent-launch-picker-catalog'
import type { AgentPickerEntry } from './agent-launch-picker'
it('uses listed Claude alias efforts for a saved resolved model', () => {
const entry: AgentPickerEntry = {
agent: 'claude',
label: 'Claude',
rows: [],
surfaces: ['terminal', 'chat'],
defaultSurface: 'terminal',
terminal: {},
structured: {},
catalogRead: 'settled',
coherentCatalog: true,
catalog: {
origin: 'probe',
fetchedAt: 1,
models: [
{
id: 'opus',
resolvedModel: 'claude-opus-5-5',
label: 'Opus',
isDefault: false,
efforts: [
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' }
]
}
]
}
}
const options = agentPickerEntryOptions(entry, 'claude-opus-5-5', 'terminal')
expect(options.find(({ id }) => id === 'effort')?.kind).toMatchObject({
choices: [{ value: 'low' }, { value: 'medium' }, { value: 'high' }]
})
})
@@ -1,166 +0,0 @@
import { expect, it } from 'vitest'
import recording from '../../fixtures/agent-picker-cli-recordings.json'
import { modelMenuOptions, type ModelMenuInput } from './model-menu-options'
import { getAgentSessionOptionLaunchCatalog } from './agent-session-option-catalog'
import type { AgentSessionModelCatalogResult } from '../agent-session-wire'
const seed = getAgentSessionOptionLaunchCatalog('codex')!
const input: ModelMenuInput = {
agent: 'codex',
surface: 'chat',
seed,
newLaunch: true,
seedsModel: true,
coherentCatalog: true
}
const recorded: AgentSessionModelCatalogResult = {
origin: 'probe',
fetchedAt: 1,
listingNamesConfiguredModel: true,
models: recording.modelList.data.map((row) => ({
id: row.id,
label: row.displayName,
isDefault: true,
defaultEffort: row.defaultReasoningEffort,
efforts: row.supportedReasoningEfforts.map((effort) => ({
value: effort.reasoningEffort,
label: effort.reasoningEffort
}))
}))
}
it('uses listed membership and live efforts, including when a seed names the same model', () => {
const menu = modelMenuOptions(recorded, {
...input,
seed: {
...seed,
models: [
{
id: 'gpt-5.6-sol',
label: 'Seed',
options: [
{
id: 'effort',
label: 'Effort',
kind: {
type: 'select',
choices: [{ value: 'seed-only', label: 'Seed' }],
defaultValue: 'seed-only'
},
apply: {}
}
]
}
]
},
saved: { model: 'gpt-5.6-sol' }
})
expect(menu.rows.map((row) => row.id)).toEqual(['gpt-5.6-sol'])
expect(menu.rows[0].efforts.map((row) => row.value)).toEqual([
'low',
'medium',
'high',
'xhigh',
'max',
'ultra'
])
expect(menu.descriptors.find((row) => row.id === 'effort')?.kind).toMatchObject({
choices: [
{ value: 'low' },
{ value: 'medium' },
{ value: 'high' },
{ value: 'xhigh' },
{ value: 'max' },
{ value: 'ultra' }
]
})
})
it('distinguishes listing, unavailable discovery, coherent empty and legacy empty', () => {
const listing = modelMenuOptions({ origin: 'unknown', listingInProgress: true }, input)
expect(listing.status).toBe('listing')
expect(listing.rows).toEqual([])
expect(listing.descriptors.find((row) => row.id === 'model')?.settable).toBe(false)
for (const answer of [undefined, { origin: 'unknown' } as const]) {
expect(modelMenuOptions(answer, input).status).toBe('builtin')
expect(modelMenuOptions(answer, input).rows.length).toBeGreaterThan(0)
}
expect(modelMenuOptions({ origin: 'probe', fetchedAt: 1, models: [] }, input)).toMatchObject({
status: 'listed',
rows: []
})
expect(
modelMenuOptions(
{ origin: 'probe', fetchedAt: 1, models: [] },
{ ...input, coherentCatalog: false }
).status
).toBe('builtin')
expect(
modelMenuOptions(recorded, { ...input, coherentCatalog: false }).rows.map((row) => row.id)
).toEqual(['gpt-5.6-sol'])
})
it('keeps a literal saved unlisted model and effort read-only', () => {
const menu = modelMenuOptions(recorded, {
...input,
saved: { model: 'retired-account-model', effort: 'old-level' }
})
expect(menu.descriptors.find((row) => row.id === 'model')?.kind).toMatchObject({
currentValue: 'retired-account-model',
choices: expect.arrayContaining([
{
value: 'retired-account-model',
label: 'retired-account-model',
description: 'retired-account-model'
}
])
})
expect(menu.descriptors.find((row) => row.id === 'effort')).toMatchObject({
settable: false,
kind: { currentValue: 'old-level', choices: [{ value: 'old-level', label: 'old-level' }] }
})
})
it('excludes chat-only efforts on CLI surfaces and retains Config default execution modes', () => {
const live = {
origin: 'probe',
fetchedAt: 1,
models: [
{
id: 'live',
label: 'Live',
isDefault: true,
efforts: [
{ value: 'low', label: 'Low' },
{ value: 'high', label: 'High' }
],
chatEfforts: [{ value: 'ultracode', label: 'Ultracode' }]
}
]
} as const
for (const surface of ['terminal', 'textGeneration'] as const) {
const menu = modelMenuOptions(
{
...live,
models: [...live.models].map((row) => ({
...row,
efforts: [...row.efforts],
chatEfforts: [...row.chatEfforts]
}))
},
{ ...input, surface, saved: { model: 'live' } }
)
expect(menu.descriptors.find((row) => row.id === 'effort')?.kind).toMatchObject({
choices: [{ value: 'low' }, { value: 'high' }]
})
}
const ownSeed = { ...seed, models: [{ id: 'default', label: 'Config default', options: [] }] }
const pi = modelMenuOptions(recorded, { ...input, agent: 'pi', seed: ownSeed })
expect(pi.rows.map((row) => row.id)).toEqual(['default', 'gpt-5.6-sol'])
const cursor = modelMenuOptions(undefined, {
...input,
agent: 'cursor',
seed: getAgentSessionOptionLaunchCatalog('cursor')!
})
expect(cursor.rows.some((row) => row.id === 'auto')).toBe(true)
})
@@ -1,68 +0,0 @@
{
"capture": "codex-cli 0.149.0, 2026-08-21; model/list first row and thread/start policy fields; workspace paths omitted",
"modelList": {
"data": [
{
"id": "gpt-5.6-sol",
"model": "gpt-5.6-sol",
"upgrade": null,
"upgradeInfo": null,
"availabilityNux": {
"message": "Our most capable model yet. GPT-5.6 Sol can tackle complex code changes, dig into research, produce polished documents, and take on your most ambitious work. Sol is highly capable at lower reasoning efforts\u2014try starting lower, then turn it up for harder jobs."
},
"displayName": "GPT-5.6-Sol",
"description": "Latest frontier agentic coding model.",
"modelSpecialty": null,
"hidden": false,
"supportedReasoningEfforts": [
{
"reasoningEffort": "low",
"description": "Fast responses with lighter reasoning"
},
{
"reasoningEffort": "medium",
"description": "Balances speed and reasoning depth for everyday tasks"
},
{
"reasoningEffort": "high",
"description": "Greater reasoning depth for complex problems"
},
{
"reasoningEffort": "xhigh",
"description": "Extra high reasoning depth for complex problems"
},
{
"reasoningEffort": "max",
"description": "Maximum reasoning depth for the hardest problems"
},
{
"reasoningEffort": "ultra",
"description": "Maximum reasoning with automatic task delegation"
}
],
"defaultReasoningEffort": "low",
"inputModalities": ["text", "image"],
"supportsPersonality": false,
"multiAgentVersion": "v2",
"additionalSpeedTiers": ["fast"],
"serviceTiers": [
{
"id": "priority",
"name": "Fast",
"description": "1.5x speed, increased usage"
}
],
"defaultServiceTier": null,
"isDefault": true
}
],
"nextCursor": null
},
"policy": {
"approvalPolicy": "on-request",
"approvalsReviewer": "user",
"sandbox": {
"type": "workspaceWrite"
}
}
}
-42
View File
@@ -1,42 +0,0 @@
import { describe, expect, it } from 'vitest'
import {
isExpectedAgentProcess,
recognizeAgentProcessFromCommandLine
} from './agent-status/process/agent-process-recognition'
import { detectAgentStatusFromTitle } from './agent-status/title/agent-title-status'
import { resolveExplicitTerminalTitleAgentType } from './agent-status/title/terminal-title-agent-type'
import { jcodePaneTitleStatus } from './agent-status/title/providers/jcode-terminal-title'
describe('Jcode pane identity and title status', () => {
it('recognizes the platform binary the Linux release wrapper execs', () => {
for (const command of [
'/home/dev/.local/bin/jcode-versions/0.99.1/jcode-linux-x86_64.bin',
'/home/dev/.local/bin/jcode-versions/0.99.1/jcode-linux-aarch64.bin --resume fox'
]) {
expect(recognizeAgentProcessFromCommandLine(command)?.agent).toBe('jcode')
expect(isExpectedAgentProcess(command.split(' ')[0], 'jcode')).toBe(true)
}
expect(recognizeAgentProcessFromCommandLine('jcode-helper')).toBeNull()
})
it('reads the turn tail only in a Jcode pane', () => {
for (const title of [
'🌐 jcode/fountain Duck · work ~2s',
'🦊 Fix codex hooks · +12 -3 · work ~2m05s',
'🐩 jcode Poodle · working'
]) {
expect(jcodePaneTitleStatus(title, 'jcode')).toBe('working')
expect(jcodePaneTitleStatus(title, 'claude')).toBeNull()
}
expect(jcodePaneTitleStatus('jcode SSH devbox fox · last ~1h05m', 'jcode')).toBe('idle')
// Title-only readers see the identity at rest, never a turn a later title would drop.
expect(detectAgentStatusFromTitle('🌐 jcode/fountain Duck · work ~2s')).toBe('idle')
expect(detectAgentStatusFromTitle('🦊 Improve session tabs · work ~2m05s')).toBeNull()
})
it('identifies Jcode from its server-qualified session title', () => {
expect(resolveExplicitTerminalTitleAgentType('🌐 jcode/fountain Duck · work ~2s')).toBe('jcode')
expect(resolveExplicitTerminalTitleAgentType('✳ Jcode hooks')).not.toBe('jcode')
expect(resolveExplicitTerminalTitleAgentType('jcode/scripts')).not.toBe('jcode')
})
})