fix(lint): enable anti-slop/no-object-parameters (#20781)

The rule rejects the broad `object` type on any function input (declarations,
expressions, arrows, methods, call/construct signatures, function types), plus
local aliases and unions that resolve to `object`. `object` accepts every
non-primitive while exposing no properties, so it documents nothing and pushes
callers into assertions at the boundary.

Fixes all 185 violations across src, config, tests and mobile, and flips the
rule from "off" to "error" in config/oxlint-anti-slop.json.

Approach: replace each `object` input with the type its owner already has.
Most sites took an existing domain type or a type-only import (36 added);
40 new aliases name shapes that had none. Where a value is genuinely only
compared by reference, it gets a named identity token instead of a shape --
`Record<string, never>`, the built-in `WeakKey`, or a `unique symbol` brand,
matching the branding already used in src/shared. Same treatment for WeakMap
and Map key parameters. Two `as unknown as` casts became unnecessary once the
parameter carried a real type and were removed; no new casts were added.

Suppressions added: none. No `oxlint-disable` for this rule anywhere, and no
max-lines disable or per-file bump.

Three files sat exactly at their max-lines cap, so the added type imports were
made line-neutral rather than suppressed:
- src/main/ipc/browser.ts exports the existing guest-registration args type
  (renamed BrowserGuestArgs) so browser.test.ts reuses it on one line.
- pane-scroll.ts takes TerminalScrollIntentTarget through the existing
  pane-manager-types import via a type-only re-export.
- direct-rpc-client.ts drops the identity parameter entirely: the session
  check moved into the sendProbe callback that owns the token.

Verified: anti-slop config reports zero violations over src config tests
mobile; run-typecheck-projects-in-parallel exits 0; 144 affected test files
pass (1749 tests); oxlint and oxfmt clean on all changed files. Mobile has no
runnable test/typecheck target in this worktree (expo is not installed), so
its 6 files were typechecked against a standalone config and diffed against
the base branch -- error sets are byte-identical, including test files.
This commit is contained in:
Neil
2026-09-15 01:59:58 -07:00
committed by GitHub
parent e4a9d24e0c
commit bfdec26352
121 changed files with 593 additions and 298 deletions
@@ -19,6 +19,10 @@ vi.mock('electron', () => ({
import { _internals } from './hook-service'
type SessionFixture = { id: string; parentID?: string }
/** The session half of the SDK client, as the plugin's ancestry lookup uses it. */
type SessionClientFixture = {
list: (options?: { signal?: AbortSignal }) => Promise<{ data: SessionFixture[] }>
}
type PluginEvent = { type: string; properties?: Record<string, unknown> }
type PluginEventHandler = (input: { event: PluginEvent }) => Promise<void>
type PluginHooks = { event: PluginEventHandler; dispose?: () => Promise<void> }
@@ -83,7 +87,7 @@ describe('OpenCode plugin fail-open ownership', () => {
return loadHooksWithSession({ list })
}
async function loadHooksWithSession(session: object): Promise<PluginHooks> {
async function loadHooksWithSession(session: SessionClientFixture): Promise<PluginHooks> {
return loadHooksWithContext({ client: { session } })
}
@@ -19,6 +19,12 @@ vi.mock('electron', () => ({
import { _internals } from './hook-service'
type SessionFixture = { id: string; parentID?: string }
/** The plugin probes both SDK call conventions — current `(parameters, options)` and legacy
* single-options — so fixtures for one session-client method differ in arity. */
type SessionClientCall = (...args: never[]) => Promise<{ data: SessionFixture[] }>
type SessionClientFixture = { list: SessionClientCall; get?: SessionClientCall }
type PluginEvent = { type: string; properties?: Record<string, unknown> }
type PluginEventHandler = (input: { event: PluginEvent }) => Promise<void>
type PluginHooks = { event: PluginEventHandler; dispose?: () => Promise<void> }
@@ -83,7 +89,7 @@ describe('OpenCode plugin lifecycle delivery', () => {
return loadHooksWithSession({ list })
}
async function loadHooksWithSession(session: object): Promise<PluginHooks> {
async function loadHooksWithSession(session: SessionClientFixture): Promise<PluginHooks> {
const pluginPath = join(tempDir, 'orca-opencode-status.mjs')
writeFileSync(pluginPath, _internals.getOpenCodePluginSource())
const module = (await import(pathToFileURL(pluginPath).href)) as {