From b3e5b9a5e0c47cbc7c6f56072e7f6a8a9daea4be Mon Sep 17 00:00:00 2001 From: OrcaWin Date: Thu, 29 Oct 2026 11:38:24 -0700 Subject: [PATCH] test: remove schema inventories and redundant capability checks (#36040) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> --- config/scripts/generate-plugin-schemas.mjs | 4 +- .../db-task-promotion-projection.test.ts | 49 ------ .../omp-model-switch-capability.test.ts | 20 --- ...runtime-rpc-client-capability-peek.test.ts | 11 -- .../manifest/plugin-json-schema.test.ts | 145 +----------------- .../plugins/manifest/plugin-json-schema.ts | 7 +- .../manifest/plugin-schema-field-docs.test.ts | 79 ---------- .../manifest/plugin-schema-field-docs.ts | 4 +- 8 files changed, 7 insertions(+), 312 deletions(-) delete mode 100644 src/shared/plugins/manifest/plugin-schema-field-docs.test.ts diff --git a/config/scripts/generate-plugin-schemas.mjs b/config/scripts/generate-plugin-schemas.mjs index 34db9c3e1ce..30d04b06bfc 100644 --- a/config/scripts/generate-plugin-schemas.mjs +++ b/config/scripts/generate-plugin-schemas.mjs @@ -1,6 +1,4 @@ -// Why: the zod schemas in src/shared/plugins are the only definition; this writes the published -// JSON Schemas and author references from them. The drift test in plugin-json-schema.test.ts -// fails when these files fall behind. +// Generate published JSON Schemas and author references from the Zod schemas. import { mkdirSync, writeFileSync } from 'node:fs' import path from 'node:path' import { loadPluginSchemaModule, REPO_ROOT } from './plugin-schema-module-loader.mjs' diff --git a/src/main/runtime/orchestration/db-task-promotion-projection.test.ts b/src/main/runtime/orchestration/db-task-promotion-projection.test.ts index 845aff1c78c..a65bf0cef6a 100644 --- a/src/main/runtime/orchestration/db-task-promotion-projection.test.ts +++ b/src/main/runtime/orchestration/db-task-promotion-projection.test.ts @@ -99,55 +99,6 @@ describe('task promotion query allocation', () => { } ) - it.each(['ready', 'failed', 'blocked'] as const)( - 'leaves a dependent pending when another dependency is %s', - (status) => { - const db = createDb() - const target = db.createTask({ runId: 'run_legacy_local', spec: 'Completing task' }) - const other = db.createTask({ runId: 'run_legacy_local', spec: 'Other dependency' }) - if (status !== 'ready') { - db.updateTaskStatus(other.id, status) - } - const child = db.createTask({ - runId: 'run_legacy_local', - spec: 'Dependent task', - deps: [target.id, other.id] - }) - - db.updateTaskStatus(target.id, 'completed') - - expect(db.getTask(child.id)?.status).toBe('pending') - } - ) - - it.each(['not-json', 'null', '{}', '2'])( - 'rolls back completion and earlier promotions on persisted malformed deps %s', - (deps) => { - const db = createDb() - const target = db.createTask({ runId: 'run_legacy_local', spec: 'Completing task' }) - const child = db.createTask({ - runId: 'run_legacy_local', - spec: 'Promoted before malformed row', - deps: [target.id] - }) - const run = db.createRun({ - objective: 'Other run', - coordinatorHandle: 'term_other', - coordinatorPaneKey: 'tab_other:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa' - }) - const open = db.createTask({ runId: run.id, spec: 'Other dependency' }) - const malformed = db.createTask({ runId: run.id, spec: 'Malformed task', deps: [open.id] }) - db.db.prepare('UPDATE tasks SET deps = ? WHERE id = ?').run(deps, malformed.id) - - expect(() => db.updateTaskStatus(target.id, 'completed', 'Must roll back')).toThrow() - - expect(db.getTask(target.id)).toEqual(target) - expect(db.getTask(child.id)).toEqual(child) - expect(db.getTask(malformed.id)).toMatchObject({ status: 'pending', deps }) - expect(db.db.isTransaction).toBe(false) - } - ) - it('leaves promotion inside the caller-owned transaction', () => { const db = createDb() const target = db.createTask({ runId: 'run_legacy_local', spec: 'Completing task' }) diff --git a/src/renderer/src/components/native-chat/omp-model-switch-capability.test.ts b/src/renderer/src/components/native-chat/omp-model-switch-capability.test.ts index 7403053bf57..24f8a8ece49 100644 --- a/src/renderer/src/components/native-chat/omp-model-switch-capability.test.ts +++ b/src/renderer/src/components/native-chat/omp-model-switch-capability.test.ts @@ -1,10 +1,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import { clearNativeChatSessionOptionCacheForTests } from './native-chat-session-option-cache' import { createNativeChatPtySessionOptions } from '../../../../shared/native-chat-pty-session-options' -import { - normalizeAgentStatusPayload, - pickParsedAgentStatusPayload -} from '../../../../shared/agent-status-types' describe('OMP model command capability', () => { beforeEach(() => clearNativeChatSessionOptionCacheForTests()) @@ -39,20 +35,4 @@ describe('OMP model command capability', () => { } } ) - - it('preserves only the recognized capability through normalization and remote projection', () => { - for (const command of ['orca-model', 'arbitrary-command', undefined]) { - const payload = normalizeAgentStatusPayload({ - state: 'done', - agentType: 'omp', - modelSwitchCommand: command - }) - if (!payload) { - throw new Error('expected status') - } - expect(pickParsedAgentStatusPayload(payload).modelSwitchCommand).toBe( - command === 'orca-model' ? command : undefined - ) - } - }) }) diff --git a/src/renderer/src/runtime/runtime-rpc-client-capability-peek.test.ts b/src/renderer/src/runtime/runtime-rpc-client-capability-peek.test.ts index 1f3b4fd185a..e991709d198 100644 --- a/src/renderer/src/runtime/runtime-rpc-client-capability-peek.test.ts +++ b/src/renderer/src/runtime/runtime-rpc-client-capability-peek.test.ts @@ -40,17 +40,6 @@ afterEach(() => { }) describe('peekRuntimeEnvironmentCapability', () => { - it('answers undefined without issuing a request when no status is cached', () => { - expect(peekRuntimeEnvironmentCapability('env-cold', CAPABILITY)).toBeUndefined() - expect(runtimeEnvironmentCall).not.toHaveBeenCalled() - }) - - it('answers a cached positive verdict synchronously', async () => { - runtimeEnvironmentCall.mockResolvedValue(statusReply([CAPABILITY])) - await runtimeEnvironmentSupportsCapability('env-new', CAPABILITY) - expect(peekRuntimeEnvironmentCapability('env-new', CAPABILITY)).toBe(true) - }) - it('caches an old host answer for the TTL while async callers still re-probe it', async () => { vi.useFakeTimers() vi.setSystemTime(new Date(0)) diff --git a/src/shared/plugins/manifest/plugin-json-schema.test.ts b/src/shared/plugins/manifest/plugin-json-schema.test.ts index 599ad32fc00..016cee81d73 100644 --- a/src/shared/plugins/manifest/plugin-json-schema.test.ts +++ b/src/shared/plugins/manifest/plugin-json-schema.test.ts @@ -1,37 +1,12 @@ import { readdirSync, readFileSync } from 'node:fs' import path from 'node:path' import { describe, expect, it } from 'vitest' -import { z } from 'zod' -import { - catalogEntryFixture, - catalogFixture, - compilePluginJsonSchema as compile -} from './plugin-json-schema.test-fixture' -import { - pluginCatalogJsonSchema, - pluginManifestJsonSchema, - pluginSchemaGeneratedFiles, - type PluginJsonSchema -} from './plugin-json-schema' -import { parsePluginManifest, pluginManifestV2Object } from './plugin-manifest' -import { pluginCatalogDocumentSchema, pluginCatalogSchema } from '../catalog/plugin-catalog' +import { compilePluginJsonSchema as compile } from './plugin-json-schema.test-fixture' +import { pluginManifestJsonSchema } from './plugin-json-schema' +import { parsePluginManifest } from './plugin-manifest' const REPO_ROOT = path.resolve(import.meta.dirname, '..', '..', '..', '..') -/** Every property in the schema with its JSON pointer, including fragments and nested objects. */ -function properties(schema: PluginJsonSchema, pointer = ''): [string, PluginJsonSchema][] { - const own = Object.entries(schema.properties ?? {}).flatMap(([key, node]) => { - const field = typeof node === 'object' ? node : {} - const at = `${pointer}/properties/${key}` - const entry: [string, PluginJsonSchema] = [at, field] - return [entry, ...properties(field, at)] - }) - const defs = Object.entries(schema.$defs ?? {}).flatMap(([name, def]) => - properties(def, `${pointer}/$defs/${name}`) - ) - return [...own, ...defs] -} - function manifestFixtures(): { file: string; raw: unknown }[] { return ['examples/plugins', 'resources/plugins/launch'].flatMap((dir) => readdirSync(path.join(REPO_ROOT, dir), { withFileTypes: true }) @@ -41,98 +16,7 @@ function manifestFixtures(): { file: string; raw: unknown }[] { ) } -type ZodField = [path: string, field: z.core.$ZodType] - -/** Unwraps optional/default/catch/pipe layers to the object or array that holds child fields. */ -function container(schema: z.core.$ZodType): z.core.$ZodType { - if ( - schema instanceof z.ZodOptional || - schema instanceof z.ZodDefault || - schema instanceof z.ZodPrefault || - schema instanceof z.ZodCatch - ) { - return container(schema.def.innerType) - } - return schema instanceof z.ZodPipe ? container(schema.def.in) : schema -} - -/** Every object field under `schema` with its dotted path, as declared (so it carries its meta). */ -function zodFields(schema: z.core.$ZodType, at = ''): ZodField[] { - const inner = container(schema) - if (inner instanceof z.ZodArray) { - return zodFields(inner.def.element, `${at}[]`) - } - if (!(inner instanceof z.ZodObject)) { - return [] - } - return Object.entries(inner.def.shape).flatMap(([key, field]) => [ - [`${at}.${key}`, field] satisfies ZodField, - ...zodFields(field, `${at}.${key}`) - ]) -} - -/** A catch layer accepts anything; examples must satisfy the shape it guards. */ -function strict(schema: z.core.$ZodType): z.core.$ZodType { - return schema instanceof z.ZodCatch ? strict(schema.def.innerType) : schema -} - -function examplesOf(field: z.core.$ZodType): unknown[] { - const examples: unknown = z.globalRegistry.get(field)?.examples - return Array.isArray(examples) ? examples : [] -} - describe('published plugin schemas', () => { - it('match the committed files (run `pnpm generate:plugin-schemas` when this fails)', () => { - for (const [file, content] of Object.entries(pluginSchemaGeneratedFiles())) { - const committed = readFileSync(path.join(REPO_ROOT, file), 'utf8') - expect(committed, `${file} is stale: run pnpm generate:plugin-schemas`).toBe(content) - } - }) - - it.each([ - ['manifest', pluginManifestJsonSchema()], - ['catalog', pluginCatalogJsonSchema()] - ])('documents every %s field with a description and a since-version', (_name, schema) => { - // Why skip $ref fields: they point at a fragment, which is checked below. - for (const [pointer, field] of properties(schema).filter(([, field]) => !field.$ref)) { - expect(field.description, pointer).toBeTruthy() - expect(field['x-orca-since'], pointer).toBeTruthy() - } - for (const [name, def] of Object.entries(schema.$defs ?? {})) { - expect(def.description, name).toBeTruthy() - } - }) - - it.each([ - ['manifest', pluginManifestJsonSchema()], - ['catalog', pluginCatalogJsonSchema()] - ])('accepts every documented %s example', (_name, schema) => { - const { ajv } = compile(schema) - for (const [pointer, field] of properties(schema)) { - for (const example of field.examples ?? []) { - const validate = ajv.getSchema(`${schema.$id}#${pointer}`) - expect(validate?.(example), `${pointer}: ${JSON.stringify(example)}`).toBe(true) - } - } - }) - - it.each([ - ['manifest', pluginManifestV2Object], - ['catalog', pluginCatalogDocumentSchema] - ])('accepts every documented %s example at runtime too', (_name, root) => { - const fields = zodFields(root) - expect(fields.length).toBeGreaterThan(10) - const examples = fields.flatMap(([at, field]) => - examplesOf(field).map((example) => ({ at, field, example })) - ) - expect(examples.length).toBeGreaterThan(5) - for (const { at, field, example } of examples) { - expect(z.safeParse(strict(field), example).success, `${at}: ${JSON.stringify(example)}`).toBe( - true - ) - } - }) - it('agrees with the runtime on every bundled and example v2 manifest', () => { const { validate } = compile(pluginManifestJsonSchema()) const v2 = manifestFixtures().filter(({ raw }) => @@ -144,27 +28,4 @@ describe('published plugin schemas', () => { expect(parsePluginManifest(raw), file).toMatchObject({ ok: true }) } }) - - it('accepts a release-bearing catalog Orca accepts', () => { - const { validate } = compile(pluginCatalogJsonSchema()) - const catalog = { - $schema: pluginCatalogJsonSchema().$id, - ...catalogFixture([ - catalogEntryFixture( - {}, - { - name: 'Gleam', - fileTypes: ['gleam'], - license: 'Apache-2.0', - repository: 'https://github.com/acme/gleam', - homepage: 'https://gleam.example.com', - updatedAt: '2026-10-20T09:30:00Z', - changelog: 'Highlights use expressions.' - } - ) - ]) - } - expect(validate(catalog), JSON.stringify(validate.errors)).toBe(true) - expect(pluginCatalogSchema.parse(catalog).plugins).toHaveLength(1) - }) }) diff --git a/src/shared/plugins/manifest/plugin-json-schema.ts b/src/shared/plugins/manifest/plugin-json-schema.ts index 14eb8c0cd4e..df4d43d8b92 100644 --- a/src/shared/plugins/manifest/plugin-json-schema.ts +++ b/src/shared/plugins/manifest/plugin-json-schema.ts @@ -14,9 +14,7 @@ import { export const PLUGIN_SCHEMA_DIRECTORY = 'docs/schemas/plugins' export const PLUGIN_MANIFEST_SCHEMA_FILE = 'orca-plugin.v2.schema.json' export const PLUGIN_CATALOG_SCHEMA_FILE = 'orca-catalog.v2.schema.json' -/** Git ref the published `$id` points at. Why `main` for now: no release ships v2 yet; switch to - * the release tag that does, so editors only offer fields a shipped Orca reads. A test enforces - * the switch once that tag exists. */ +/** Git ref for published schemas; switch to the first v2 release tag when it ships. */ export const PLUGIN_SCHEMA_GIT_REF = 'main' export const PLUGIN_SCHEMA_BASE_URL = `https://raw.githubusercontent.com/stablyai/orca/${PLUGIN_SCHEMA_GIT_REF}/${PLUGIN_SCHEMA_DIRECTORY}/` /** The starter plugin authors copy; it carries the schema so completion works offline. */ @@ -58,8 +56,7 @@ export function pluginCatalogJsonSchema(): PluginJsonSchema { ) } -/** Every generated file, keyed by repo-relative path. One list keeps the writer and the drift - * test from disagreeing about what is generated. */ +/** Every generated file, keyed by repo-relative path, for the schema writer. */ export function pluginSchemaGeneratedFiles(): Record { const manifest = pluginManifestJsonSchema() const catalog = pluginCatalogJsonSchema() diff --git a/src/shared/plugins/manifest/plugin-schema-field-docs.test.ts b/src/shared/plugins/manifest/plugin-schema-field-docs.test.ts deleted file mode 100644 index 19c9dc392e9..00000000000 --- a/src/shared/plugins/manifest/plugin-schema-field-docs.test.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { execFileSync } from 'node:child_process' -import path from 'node:path' -import { describe, expect, it } from 'vitest' -import { PLUGIN_SCHEMA_GIT_REF } from './plugin-json-schema' -import { satisfiesOrcaEngineRange } from './plugin-manifest' -import { PLUGIN_MANIFEST_V2_SINCE, PLUGIN_SCHEMA_SINCE_V1 } from './plugin-schema-field-docs' - -const REPO_ROOT = path.resolve(import.meta.dirname, '..', '..', '..', '..') - -function git(args: string[]): string | null { - try { - return execFileSync('git', args, { cwd: REPO_ROOT, encoding: 'utf8', windowsHide: true }) - } catch { - return null - } -} - -/** Release versions, oldest first. Empty in shallow CI checkouts, which skip these checks. */ -function releaseVersions(): string[] { - return (git(['tag', '--list', 'v*']) ?? '') - .split('\n') - .filter((tag) => /^v\d+\.\d+\.\d+$/.test(tag)) - .map((tag) => tag.slice(1)) - .sort((a, b) => (a === b ? 0 : satisfiesOrcaEngineRange(a, `>=${b}`) ? 1 : -1)) -} - -function fileAt(version: string, file: string): string | null { - return git(['show', `v${version}:${file}`]) -} - -function hasFileAt(version: string, file: string): boolean { - return git(['cat-file', '-e', `v${version}:${file}`]) !== null -} - -/** First version holding `file`, by binary search: once plugins shipped, the file stayed. */ -function firstVersionWith(versions: readonly string[], file: string): string | undefined { - let low = 0 - let high = versions.length - while (low < high) { - const middle = Math.floor((low + high) / 2) - const version = versions[middle] - if (version !== undefined && hasFileAt(version, file)) { - high = middle - } else { - low = middle + 1 - } - } - return versions[low] -} - -describe('schema since-versions', () => { - it('names the first release that read plugins as the v1 baseline', () => { - const versions = releaseVersions() - if (versions.length === 0) { - return - } - const first = firstVersionWith(versions, 'src/shared/plugins/plugin-manifest.ts') - expect(first).toBe(PLUGIN_SCHEMA_SINCE_V1) - }) - - // Why: authors gate on this version, so it must name a release that really reads manifest v2. - it('names the first release tag that ships manifest v2', () => { - const first = releaseVersions().find((version) => - satisfiesOrcaEngineRange(version, `>=${PLUGIN_MANIFEST_V2_SINCE}`) - ) - if (!first) { - return - } - const manifest = fileAt(first, 'src/shared/plugins/plugin-manifest.ts') ?? '' - expect( - manifest.includes('z.literal(2)'), - `v${first} ships without manifest v2: bump PLUGIN_MANIFEST_V2_SINCE to the release that does` - ).toBe(true) - expect( - PLUGIN_SCHEMA_GIT_REF, - `v${first} shipped: point PLUGIN_SCHEMA_GIT_REF at its tag and regenerate` - ).toBe(`v${PLUGIN_MANIFEST_V2_SINCE}`) - }) -}) diff --git a/src/shared/plugins/manifest/plugin-schema-field-docs.ts b/src/shared/plugins/manifest/plugin-schema-field-docs.ts index f2519ce2135..d9f092f582b 100644 --- a/src/shared/plugins/manifest/plugin-schema-field-docs.ts +++ b/src/shared/plugins/manifest/plugin-schema-field-docs.ts @@ -1,9 +1,7 @@ /** First release that read plugins: manifest v1, its first seven contribution points, every * capability, event and built-in command action of that era. */ export const PLUGIN_SCHEMA_SINCE_V1 = '1.4.160' -/** First release that reads manifest v2, the v2 catalog and the fields that arrived with them: - * the release after the latest tag when v2 landed. A test fails once a tag at or above it - * ships without v2, so the release that does ship v2 bumps this once if needed. */ +/** First release planned to read manifest v2, the v2 catalog and their new fields. */ export const PLUGIN_MANIFEST_V2_SINCE = '1.4.245' type PluginFieldDoc = {