mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
[CI] Reuse Windows resolver imports and retire unused helper tests (#28296)
* [CI] Retire the weak local title-corpus comparison * [CI] Retire tests for seven unconsumed helper modules * [CI] Reset the Windows launch resolver graph once per group
This commit is contained in:
@@ -1,53 +0,0 @@
|
||||
import {
|
||||
existsSync,
|
||||
lstatSync,
|
||||
mkdirSync,
|
||||
mkdtempSync,
|
||||
readFileSync,
|
||||
rmSync,
|
||||
writeFileSync
|
||||
} from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { mirrorOmpPersistentSqliteFiles } from './omp-sqlite-overlay'
|
||||
|
||||
const tempDirs: string[] = []
|
||||
|
||||
function makeTempDir(): string {
|
||||
const dir = mkdtempSync(join(tmpdir(), 'orca-omp-sqlite-overlay-'))
|
||||
tempDirs.push(dir)
|
||||
return dir
|
||||
}
|
||||
|
||||
describe('OMP SQLite overlay persistence', () => {
|
||||
afterEach(() => {
|
||||
for (const dir of tempDirs.splice(0)) {
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
it('replaces overlay-local SQLite files with source-backed DB files', () => {
|
||||
const root = makeTempDir()
|
||||
const sourceDir = join(root, 'source-agent')
|
||||
const overlayDir = join(root, 'overlay-agent')
|
||||
mkdirSync(overlayDir, { recursive: true })
|
||||
writeFileSync(join(overlayDir, 'agent.db'), 'overlay main')
|
||||
writeFileSync(join(overlayDir, 'agent.db-wal'), 'overlay wal')
|
||||
|
||||
const mirroredEntries = mirrorOmpPersistentSqliteFiles(sourceDir, overlayDir)
|
||||
|
||||
expect(mirroredEntries).toContain('agent.db')
|
||||
expect(mirroredEntries).not.toContain('history.db')
|
||||
expect(readFileSync(join(sourceDir, 'agent.db'), 'utf8')).toBe('')
|
||||
expect(existsSync(join(sourceDir, 'agent.db-wal'))).toBe(process.platform === 'win32')
|
||||
|
||||
writeFileSync(join(overlayDir, 'agent.db'), 'new credentials')
|
||||
|
||||
expect(readFileSync(join(sourceDir, 'agent.db'), 'utf8')).toBe('new credentials')
|
||||
if (process.platform !== 'win32') {
|
||||
expect(lstatSync(join(overlayDir, 'agent.db')).isSymbolicLink()).toBe(true)
|
||||
expect(existsSync(join(overlayDir, 'agent.db-wal'))).toBe(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type { AgentResumeLaunchTargetArgs } from './agent-resume-launch-target'
|
||||
|
||||
function setNavigatorUserAgent(userAgent: string): () => void {
|
||||
@@ -40,8 +40,11 @@ async function resolveWith(
|
||||
describe('resolveAgentResumeLaunchTarget on a Windows client', () => {
|
||||
let restoreNavigator = (): void => {}
|
||||
|
||||
beforeEach(() => {
|
||||
beforeAll(() => {
|
||||
vi.resetModules()
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
restoreNavigator = setNavigatorUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64)')
|
||||
})
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { selectPaletteTypeAliasMatch } from './palette-type-alias-match'
|
||||
|
||||
const ALIASES = ['mobile emulator tab', 'mobile emulator', 'ios simulator', 'emulator'] as const
|
||||
|
||||
describe('selectPaletteTypeAliasMatch', () => {
|
||||
it('prefers the alias with the earliest match, not declaration order', () => {
|
||||
expect(selectPaletteTypeAliasMatch(ALIASES, 'emulator')).toEqual({
|
||||
text: 'emulator',
|
||||
range: { start: 0, end: 8 }
|
||||
})
|
||||
})
|
||||
|
||||
it('keeps the first alias when several match at the same offset', () => {
|
||||
expect(selectPaletteTypeAliasMatch(ALIASES, 'mobile')).toEqual({
|
||||
text: 'mobile emulator tab',
|
||||
range: { start: 0, end: 6 }
|
||||
})
|
||||
})
|
||||
|
||||
it('still reports a mid-string hit when no alias starts with the query', () => {
|
||||
expect(selectPaletteTypeAliasMatch(ALIASES, 'simulator')).toEqual({
|
||||
text: 'ios simulator',
|
||||
range: { start: 4, end: 13 }
|
||||
})
|
||||
})
|
||||
|
||||
it('returns null for an empty query or no match', () => {
|
||||
expect(selectPaletteTypeAliasMatch(ALIASES, '')).toBeNull()
|
||||
expect(selectPaletteTypeAliasMatch(ALIASES, 'browser')).toBeNull()
|
||||
expect(selectPaletteTypeAliasMatch([], 'emulator')).toBeNull()
|
||||
})
|
||||
})
|
||||
@@ -1,36 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { HermesRunRefRetainer } from './hermes-run-ref-retention'
|
||||
|
||||
describe('HermesRunRefRetainer', () => {
|
||||
it('preserves every ref and exact order below the limit', () => {
|
||||
const retainer = new HermesRunRefRetainer<{ id: string; run_at: string }>(3)
|
||||
retainer.add({ id: 'middle', run_at: '2026-05-15T09:00:00Z' })
|
||||
retainer.add({ id: 'newest', run_at: '2026-05-16T09:00:00Z' })
|
||||
retainer.add({ id: 'oldest', run_at: '2026-05-14T09:00:00Z' })
|
||||
|
||||
expect(retainer.finish()).toEqual({
|
||||
refs: [
|
||||
{ id: 'newest', run_at: '2026-05-16T09:00:00Z' },
|
||||
{ id: 'middle', run_at: '2026-05-15T09:00:00Z' },
|
||||
{ id: 'oldest', run_at: '2026-05-14T09:00:00Z' }
|
||||
],
|
||||
saturated: false
|
||||
})
|
||||
})
|
||||
|
||||
it('retains the exact newest window and reports saturation', () => {
|
||||
const retainer = new HermesRunRefRetainer<{ id: string; run_at: string }>(3)
|
||||
for (const day of [1, 5, 2, 6, 3, 4]) {
|
||||
retainer.add({ id: `day-${day}`, run_at: `2026-05-0${day}T09:00:00Z` })
|
||||
}
|
||||
|
||||
expect(retainer.finish()).toEqual({
|
||||
refs: [
|
||||
{ id: 'day-6', run_at: '2026-05-06T09:00:00Z' },
|
||||
{ id: 'day-5', run_at: '2026-05-05T09:00:00Z' },
|
||||
{ id: 'day-4', run_at: '2026-05-04T09:00:00Z' }
|
||||
],
|
||||
saturated: true
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,52 +0,0 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import {
|
||||
createLinuxProcTextReadBudget,
|
||||
LINUX_PROC_NETWORK_TABLE_MAX_BYTES,
|
||||
readLinuxProcNetworkTable,
|
||||
readLinuxProcTextWithinBudget
|
||||
} from './linux-proc-port-scan-limits'
|
||||
|
||||
describe('Linux proc port scan limits', () => {
|
||||
it('applies the network-table byte cap before retaining content', async () => {
|
||||
const readFile = vi.fn(async () => Buffer.from('table'))
|
||||
|
||||
await expect(readLinuxProcNetworkTable('/proc/net/tcp', readFile)).resolves.toBe('table')
|
||||
expect(readFile).toHaveBeenCalledWith('/proc/net/tcp', LINUX_PROC_NETWORK_TABLE_MAX_BYTES)
|
||||
})
|
||||
|
||||
it('shares one retained-byte budget across process metadata files', async () => {
|
||||
const budget = createLinuxProcTextReadBudget(5)
|
||||
const readFile = vi
|
||||
.fn<(filePath: string, maxBytes: number) => Promise<Buffer>>()
|
||||
.mockResolvedValueOnce(Buffer.from('abc'))
|
||||
.mockResolvedValueOnce(Buffer.from('de'))
|
||||
|
||||
await expect(readLinuxProcTextWithinBudget('/proc/1/comm', budget, readFile, 4)).resolves.toBe(
|
||||
'abc'
|
||||
)
|
||||
await expect(
|
||||
readLinuxProcTextWithinBudget('/proc/1/cmdline', budget, readFile, 4)
|
||||
).resolves.toBe('de')
|
||||
await expect(
|
||||
readLinuxProcTextWithinBudget('/proc/2/cmdline', budget, readFile, 4)
|
||||
).resolves.toBeUndefined()
|
||||
|
||||
expect(readFile.mock.calls).toEqual([
|
||||
['/proc/1/comm', 4],
|
||||
['/proc/1/cmdline', 2]
|
||||
])
|
||||
expect(budget.remainingBytes).toBe(0)
|
||||
})
|
||||
|
||||
it('does not debit failed metadata reads', async () => {
|
||||
const budget = createLinuxProcTextReadBudget(4)
|
||||
const readFile = vi.fn(async () => {
|
||||
throw new Error('oversized')
|
||||
})
|
||||
|
||||
await expect(
|
||||
readLinuxProcTextWithinBudget('/proc/1/cmdline', budget, readFile)
|
||||
).resolves.toBeUndefined()
|
||||
expect(budget.remainingBytes).toBe(4)
|
||||
})
|
||||
})
|
||||
@@ -1,37 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
assertMobileFileDirectoryWithinLimit,
|
||||
MOBILE_FILE_DIRECTORY_LIMIT_MESSAGE,
|
||||
MOBILE_FILE_DIRECTORY_MAX_ENTRIES,
|
||||
MOBILE_FILE_DIRECTORY_MAX_RETAINED_BYTES
|
||||
} from './mobile-file-directory-limit'
|
||||
|
||||
describe('mobile file directory limit', () => {
|
||||
it('accepts a complete directory listing within both limits', () => {
|
||||
expect(() =>
|
||||
assertMobileFileDirectoryWithinLimit([
|
||||
{ name: 'src' },
|
||||
{ name: 'README.md' },
|
||||
{ name: 'package.json' }
|
||||
])
|
||||
).not.toThrow()
|
||||
})
|
||||
|
||||
it('rejects rather than truncating an excessive entry count', () => {
|
||||
const entries = Array.from({ length: MOBILE_FILE_DIRECTORY_MAX_ENTRIES + 1 }, () => ({
|
||||
name: 'x'
|
||||
}))
|
||||
|
||||
expect(() => assertMobileFileDirectoryWithinLimit(entries)).toThrow(
|
||||
MOBILE_FILE_DIRECTORY_LIMIT_MESSAGE
|
||||
)
|
||||
})
|
||||
|
||||
it('rejects a listing whose names exceed the retained-byte limit', () => {
|
||||
const name = 'x'.repeat(MOBILE_FILE_DIRECTORY_MAX_RETAINED_BYTES / 2)
|
||||
|
||||
expect(() => assertMobileFileDirectoryWithinLimit([{ name }])).toThrow(
|
||||
MOBILE_FILE_DIRECTORY_LIMIT_MESSAGE
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,73 +1,8 @@
|
||||
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
||||
import { homedir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { createHash, randomBytes } from 'node:crypto'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { collectAgentTitleEvidence } from './agent-title-evidence'
|
||||
import { resolveCanonicalPaneAgentIdentity } from './pane-agent-identity-adapter'
|
||||
import type { TerminalAgent } from './terminal-agent'
|
||||
|
||||
/**
|
||||
* Title regression gates for the identity-ladder migration.
|
||||
*
|
||||
* Two layers: a controlled fixture table that always runs (CI-safe), and a local characterization
|
||||
* gate over the machine's real recorded corpus. The corpus gate is not a CI prerequisite tied to
|
||||
* one developer's home — when no history exists it reports `corpus unavailable — skipped`
|
||||
* explicitly, never a silently green zero-title run. Raw titles never reach logs or failure
|
||||
* output; changed titles are reported as salted hashes plus old/new agent summaries only.
|
||||
*/
|
||||
|
||||
const RECORDED_HISTORY_DIR = 'terminal-history'
|
||||
const QUARANTINE_DIR = '.recovery-quarantine'
|
||||
|
||||
function orcaAppSupportCandidates(): string[] {
|
||||
if (process.platform === 'darwin') {
|
||||
return [join(homedir(), 'Library', 'Application Support', 'Orca')]
|
||||
}
|
||||
if (process.platform === 'win32') {
|
||||
return [join(process.env.APPDATA ?? join(homedir(), 'AppData', 'Roaming'), 'Orca')]
|
||||
}
|
||||
return [
|
||||
join(process.env.XDG_CONFIG_HOME ?? join(homedir(), '.config'), 'Orca'),
|
||||
join(process.env.XDG_DATA_HOME ?? join(homedir(), '.local', 'share'), 'Orca')
|
||||
]
|
||||
}
|
||||
|
||||
/** Deliberately shallow: `terminal-history/<session>/checkpoint.json` only, with the hidden
|
||||
* quarantine subtree excluded BY NAME so a future recursive rewrite cannot silently turn
|
||||
* quarantined recovery data into product regressions. */
|
||||
function loadRecordedTitleCorpus(): { checkpointCount: number; titles: string[] } | null {
|
||||
const root = orcaAppSupportCandidates()
|
||||
.map((candidate) => join(candidate, RECORDED_HISTORY_DIR))
|
||||
.find((candidate) => existsSync(candidate))
|
||||
if (!root) {
|
||||
return null
|
||||
}
|
||||
let checkpointCount = 0
|
||||
const titles = new Set<string>()
|
||||
for (const entry of readdirSync(root, { withFileTypes: true })) {
|
||||
if (!entry.isDirectory() || entry.name === QUARANTINE_DIR || entry.name.startsWith('.')) {
|
||||
continue
|
||||
}
|
||||
const checkpointPath = join(root, entry.name, 'checkpoint.json')
|
||||
if (!existsSync(checkpointPath)) {
|
||||
continue
|
||||
}
|
||||
const parsed: unknown = JSON.parse(readFileSync(checkpointPath, 'utf8'))
|
||||
checkpointCount += 1
|
||||
const lastTitle = (parsed as { lastTitle?: unknown }).lastTitle
|
||||
if (typeof lastTitle === 'string' && lastTitle.length > 0) {
|
||||
titles.add(lastTitle)
|
||||
}
|
||||
}
|
||||
return { checkpointCount, titles: [...titles] }
|
||||
}
|
||||
|
||||
/** What the canonical adapter answers when a title is all a pane has (the uncovered lane). */
|
||||
function canonicalTitleOnlyAgent(title: string): TerminalAgent | null {
|
||||
return resolveCanonicalPaneAgentIdentity({ title }).agent
|
||||
}
|
||||
|
||||
describe('controlled title fixtures (always run)', () => {
|
||||
const FIXTURES: readonly { name: string; title: string; expected: TerminalAgent | null }[] = [
|
||||
{
|
||||
@@ -113,44 +48,9 @@ describe('controlled title fixtures (always run)', () => {
|
||||
for (const fixture of FIXTURES) {
|
||||
it(fixture.name, () => {
|
||||
expect(collectAgentTitleEvidence(fixture.title).agent).toBe(fixture.expected)
|
||||
// The adapter's title-only lane must give the very same answer — phase 1 changes no
|
||||
// parser semantics, only provenance.
|
||||
expect(canonicalTitleOnlyAgent(fixture.title)).toBe(fixture.expected)
|
||||
expect(resolveCanonicalPaneAgentIdentity({ title: fixture.title }).agent).toBe(
|
||||
fixture.expected
|
||||
)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
describe('recorded title corpus characterization (local gate)', () => {
|
||||
it('the canonical title-only lane matches the shipped parser on every recorded title', (ctx) => {
|
||||
const corpus = loadRecordedTitleCorpus()
|
||||
if (corpus === null) {
|
||||
console.info('corpus unavailable — skipped (no recorded terminal history on this machine)')
|
||||
ctx.skip()
|
||||
return
|
||||
}
|
||||
// A machine WITH history must never pass on an empty read — that would be a silently green
|
||||
// zero-title run, not a characterization.
|
||||
expect(corpus.checkpointCount).toBeGreaterThan(0)
|
||||
expect(corpus.titles.length).toBeGreaterThan(0)
|
||||
console.info(
|
||||
`corpus: ${corpus.checkpointCount} checkpoints, ${corpus.titles.length} distinct titles`
|
||||
)
|
||||
|
||||
const salt = randomBytes(16).toString('hex')
|
||||
const changed: { titleHash: string; oldAgent: string | null; newAgent: string | null }[] = []
|
||||
for (const title of corpus.titles) {
|
||||
const oldAgent = collectAgentTitleEvidence(title).agent
|
||||
const newAgent = canonicalTitleOnlyAgent(title)
|
||||
if (oldAgent !== newAgent) {
|
||||
changed.push({
|
||||
titleHash: createHash('sha256').update(`${salt}:${title}`).digest('hex').slice(0, 16),
|
||||
oldAgent,
|
||||
newAgent
|
||||
})
|
||||
}
|
||||
}
|
||||
// Report hashes and agent summaries only; a reviewer who needs the raw value inspects the
|
||||
// protected corpus on the machine that owns it.
|
||||
expect(changed).toEqual([])
|
||||
}, 60_000)
|
||||
})
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { mergePiOverlayUiSettings } from './pi-overlay-ui-settings'
|
||||
|
||||
describe('mergePiOverlayUiSettings', () => {
|
||||
it('preserves user settings while forcing Orca-only Pi UI safety settings', () => {
|
||||
const merged = mergePiOverlayUiSettings({
|
||||
defaultProvider: 'amazon-bedrock',
|
||||
hideThinkingBlock: false,
|
||||
packages: ['npm:pi-web-access'],
|
||||
terminal: {
|
||||
showImages: false,
|
||||
clearOnShrink: false
|
||||
}
|
||||
})
|
||||
|
||||
expect(merged).toEqual({
|
||||
defaultProvider: 'amazon-bedrock',
|
||||
hideThinkingBlock: true,
|
||||
packages: ['npm:pi-web-access'],
|
||||
terminal: {
|
||||
showImages: false,
|
||||
clearOnShrink: true
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('creates a valid settings object from malformed shapes', () => {
|
||||
expect(mergePiOverlayUiSettings(null)).toEqual({
|
||||
hideThinkingBlock: true,
|
||||
terminal: { clearOnShrink: true }
|
||||
})
|
||||
expect(mergePiOverlayUiSettings({ terminal: 'compact' })).toEqual({
|
||||
hideThinkingBlock: true,
|
||||
terminal: { clearOnShrink: true }
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,17 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { appendCompactedStringChunk, RETAINED_STRING_CHUNK_LIMIT } from './string-chunk-compaction'
|
||||
|
||||
describe('appendCompactedStringChunk', () => {
|
||||
it('preserves 100,000 fragments within the retained chunk limit', () => {
|
||||
const chunks: string[] = []
|
||||
let maxRetainedChunks = 0
|
||||
|
||||
for (let index = 0; index < 100_000; index += 1) {
|
||||
appendCompactedStringChunk(chunks, String.fromCharCode(97 + (index % 26)))
|
||||
maxRetainedChunks = Math.max(maxRetainedChunks, chunks.length)
|
||||
}
|
||||
|
||||
expect(maxRetainedChunks).toBeLessThanOrEqual(RETAINED_STRING_CHUNK_LIMIT)
|
||||
expect(chunks.join('')).toHaveLength(100_000)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user