diff --git a/AGENTS.md b/AGENTS.md index 6977eea47..b1136c0f1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -238,6 +238,21 @@ For the bash tool specifically: Test the contract the system exposes — not the easiest internal detail to assert. - Every new test must defend one **concrete, externally observable contract**: behavior, output shape, state transition, error mapping, or a regression-prone parsing boundary. If you cannot name the contract, do not add the test. + +### Good vs. bad test filter + +- **Name the failure mode.** Every test MUST state what a consumer observes if it regresses. Cannot name one? NEVER add it. +- **Good: transformation.** One fixture MAY prove parse/render/normalize/encode/resolve behavior when output is computed, not echoed. +- **Good: branch or boundary.** Distinct inputs, empty values, malformed input, version/provider routing, and state transitions MUST prove distinct outcomes. +- **Good: external contract.** Exact bytes/shape MAY be asserted when a provider, parser, protocol, or persisted consumer reads them. +- **Good: precedence or negative contract.** Keep explicit `false`/override-wins assertions and required absence only when they prevent a documented leak, downgrade, 400, or incompatible wire field. +- **Good: regression.** A repro MUST trigger the prior real failure path and assert the corrected observable result. +- **Bad: static echo.** NEVER test a constructor/builder merely copied a fixture or baked constant into an in-memory config/metadata field. +- **Bad: success passthrough.** NEVER assert `fn(x) === x` when `x` was already supplied/declared valid; assert a transform, rejection, or downstream effect instead. +- **Bad: wording/defaults.** NEVER assert prompt/UI boilerplate, a default literal, object existence, non-empty output, or length growth without a consumer contract. +- **Bad: duplicate rows.** Parameterized/loop rows MUST each cover a distinct branch, provider/model path, or consumer contract; delete same-path duplicates. +- **Metadata exception.** Exact metadata, identity, ordering, or `undefined` MAY remain only when a downstream consumer depends on it and the test establishes branch, precedence, negative-contract, wire, or regression evidence. +- **Termination exception.** For cyclic/large inputs, assert a bounded output, surfaced error, or state change; bare `not.toThrow()` is insufficient. - No placeholder tests, tautologies, or "the code ran" assertions (`expect(true).toBe(true)`, bare `not.toThrow()`, non-empty string checks, length-grew checks, "prompt exists" checks without semantic assertion). - Prefer contract-level tests over implementation details. Avoid asserting internal helper wiring, field assignment, singleton identity, incidental ordering, prompt boilerplate, or passthrough option forwarding unless another component depends on that exact detail. - Don't duplicate coverage across abstraction levels. If an integration test already proves the behavior, drop the narrower unit test that restates it through mocks. diff --git a/packages/agent/test/agent.test.ts b/packages/agent/test/agent.test.ts index 3bd5d72b5..39cff8591 100644 --- a/packages/agent/test/agent.test.ts +++ b/packages/agent/test/agent.test.ts @@ -1386,18 +1386,6 @@ describe("Agent", () => { expect(cwdPerCall).toEqual(["/live/repo-a", "/live/repo-b"]); }); - it("returns static metadata via the plain setter", () => { - const agent = new Agent(); - expect(agent.metadata).toBeUndefined(); - - const value = { user_id: "static" }; - agent.metadata = value; - expect(agent.metadata).toEqual({ user_id: "static" }); - - agent.metadata = undefined; - expect(agent.metadata).toBeUndefined(); - }); - it("metadataForProvider resolves dynamic value at every call when a resolver is installed", () => { const agent = new Agent(); let live = "alpha"; @@ -1416,7 +1404,6 @@ describe("Agent", () => { expect(agent.metadataForProvider("any")).toEqual({ user_id: "from-resolver" }); agent.metadata = { user_id: "from-static" }; - expect(agent.metadata).toEqual({ user_id: "from-static" }); expect(agent.metadataForProvider("any")).toEqual({ user_id: "from-static" }); }); @@ -1439,7 +1426,6 @@ describe("Agent", () => { agent.setMetadataResolver(undefined); expect(agent.metadataForProvider("any")).toEqual({ user_id: "static" }); - expect(agent.metadata).toEqual({ user_id: "static" }); }); }); diff --git a/packages/ai/test/anthropic-alignment.test.ts b/packages/ai/test/anthropic-alignment.test.ts index 21b2cad7d..081e4c982 100644 --- a/packages/ai/test/anthropic-alignment.test.ts +++ b/packages/ai/test/anthropic-alignment.test.ts @@ -412,7 +412,6 @@ describe("Anthropic request fingerprint alignment", () => { // preceding real user turn gets the fallback breakpoint. The synthetic // trailing Continue. pad must never consume it. const assistant = payload.messages?.find(message => message.role === "assistant"); - expect(assistant).toBeDefined(); const assistantContent = assistant?.content; expect(Array.isArray(assistantContent)).toBe(true); for (const block of (assistantContent ?? []) as Array<{ type: string; cache_control?: unknown }>) { @@ -2066,7 +2065,6 @@ describe("Anthropic request fingerprint alignment", () => { } | undefined )?.tls; - expect(tlsOptions).toBeDefined(); expect(tlsOptions?.rejectUnauthorized).toBe(true); expect(tlsOptions?.serverName).toBe("api.anthropic.com"); expect(tlsOptions?.ciphers).toBe(tls.DEFAULT_CIPHERS); diff --git a/packages/ai/test/auth-storage-usage-cache.test.ts b/packages/ai/test/auth-storage-usage-cache.test.ts index 6fbba57a4..b7bd296c1 100644 --- a/packages/ai/test/auth-storage-usage-cache.test.ts +++ b/packages/ai/test/auth-storage-usage-cache.test.ts @@ -473,7 +473,7 @@ describe("AuthStorage usage cache: header ingestion", () => { return fullReport; }); - expect(await storage.getApiKey("anthropic", "s")).toBe("oat-1"); + await storage.getApiKey("anthropic", "s"); expect(storage.ingestUsageHeaders("anthropic", usageHeaders("0.02", "0.3"), { sessionId: "s" })).toBe(true); now.mockReturnValue(start + 60_001); expect(storage.ingestUsageHeaders("anthropic", usageHeaders("0.05", "0.6"), { sessionId: "s" })).toBe(true); @@ -491,20 +491,17 @@ describe("AuthStorage usage cache: header ingestion", () => { const start = Date.now(); const now = vi.spyOn(Date, "now").mockReturnValue(start); const fetchSpy = vi.spyOn(claudeUsage.claudeUsageProvider, "fetchUsage").mockResolvedValue(null); - expect(await storage.getApiKey("anthropic", "legacy-session")).toBe("oat-1"); + await storage.getApiKey("anthropic", "legacy-session"); expect( storage.ingestUsageHeaders("anthropic", usageHeaders("0.02", "0.3"), { sessionId: "legacy-session" }), ).toBe(true); - let rewroteLegacyEntry = false; for (const [key, entry] of store.cache) { const payload = JSON.parse(entry.value) as { value?: UsageReport | null }; if (payload.value?.metadata?.source !== "ratelimit-headers") continue; payload.value.metadata = { source: "ratelimit-headers" }; store.cache.set(key, { value: JSON.stringify(payload), expiresAtSec: entry.expiresAtSec }); - rewroteLegacyEntry = true; } - expect(rewroteLegacyEntry).toBe(true); now.mockReturnValue(start + 60_001); expect( @@ -522,7 +519,7 @@ describe("AuthStorage usage cache: header ingestion", () => { }); it("throttles repeated header ingestion for the same credential cache key", async () => { - expect(await storage.getApiKey("anthropic", "s")).toBe("oat-1"); + await storage.getApiKey("anthropic", "s"); expect(storage.ingestUsageHeaders("anthropic", usageHeaders("0.02", "0.3"), { sessionId: "s" })).toBe(true); expect(storage.ingestUsageHeaders("anthropic", usageHeaders("0.05", "0.6"), { sessionId: "s" })).toBe(false); }); @@ -536,7 +533,7 @@ describe("AuthStorage usage cache: header ingestion", () => { return null; }); - expect(await storage.getApiKey("anthropic", "cooldown-session")).toBe("oat-1"); + await storage.getApiKey("anthropic", "cooldown-session"); expect( storage.ingestUsageHeaders("anthropic", usageHeaders("0.02", "0.3"), { sessionId: "cooldown-session", @@ -595,7 +592,7 @@ describe("AuthStorage usage cache: header ingestion", () => { const initialReport = requireAnthropicReport(await storage.fetchUsageReports()); expect(fetchSpy).toHaveBeenCalledTimes(1); expect(requireLimit(initialReport, "anthropic:extra").amount.used).toBe(12.34); - expect(await storage.getApiKey("anthropic", "sliding-session")).toBe("oat-1"); + await storage.getApiKey("anthropic", "sliding-session"); now.mockReturnValue(start + 60_000); expect( @@ -639,7 +636,7 @@ describe("AuthStorage usage cache: header ingestion", () => { expect(requireLimit(initialReport, "anthropic:7d:opus").amount.used).toBe(12); expect(calls).toBe(1); - expect(await storage.getApiKey("anthropic", "merge-session")).toBe("oat-1"); + await storage.getApiKey("anthropic", "merge-session"); const beforeIngest = Date.now(); expect(storage.ingestUsageHeaders("anthropic", usageHeaders("0.05", "0.9"), { sessionId: "merge-session" })).toBe( true, @@ -710,7 +707,7 @@ describe("AuthStorage usage cache: header ingestion", () => { expect(requireLimit(initialReport, "anthropic:7d:fable").amount.used).toBe(11); expect(calls).toBe(1); - expect(await storage.getApiKey("anthropic", "fable-session")).toBe("oat-1"); + await storage.getApiKey("anthropic", "fable-session"); expect( storage.ingestUsageHeaders("anthropic", usageHeaders("0.05", "0.9", "0.61"), { sessionId: "fable-session", diff --git a/packages/ai/test/claude-usage-headers.test.ts b/packages/ai/test/claude-usage-headers.test.ts index e159cf18c..2c3f2af46 100644 --- a/packages/ai/test/claude-usage-headers.test.ts +++ b/packages/ai/test/claude-usage-headers.test.ts @@ -96,7 +96,7 @@ describe("claude usage request headers", () => { fetch: fetchMock, }; - const report = await claudeUsageProvider.fetchUsage( + await claudeUsageProvider.fetchUsage( { provider: "anthropic", credential: { @@ -110,7 +110,6 @@ describe("claude usage request headers", () => { ctx, ); - expect(report).not.toBeNull(); expect(calls).toHaveLength(1); expect(calls[0]?.input).toBe("https://api.anthropic.com/api/oauth/usage"); @@ -119,7 +118,6 @@ describe("claude usage request headers", () => { expect(getHeaderCaseInsensitive(headers, "user-agent")).toBe(`claude-cli/${claudeCodeVersion} (external, cli)`); const beta = getHeaderCaseInsensitive(headers, "anthropic-beta"); - expect(beta).toBeDefined(); const betaTokens = beta?.split(",").map(tokenValue => tokenValue.trim()) ?? []; expect(betaTokens).toContain("claude-code-20250219"); expect(betaTokens).toContain("oauth-2025-04-20"); @@ -344,7 +342,6 @@ describe("claude usage request headers", () => { // instead of burning retries. The trailing /profile call is the expected // identity backfill for a payload/credential carrying no account identity. expect(calls.filter(url => url.endsWith("/usage"))).toEqual(["https://api.anthropic.com/api/oauth/usage"]); - expect(report).not.toBeNull(); expect(report?.limits.map(limit => limit.id)).toEqual(["anthropic:5h", "anthropic:7d"]); const session = report?.limits.find(limit => limit.id === "anthropic:5h"); const weekly = report?.limits.find(limit => limit.id === "anthropic:7d"); @@ -921,7 +918,6 @@ describe("claude ranking strategy", () => { limits, }; - expect(claudeRankingStrategy.scopeLimits).toBeDefined(); const scopeLimits = claudeRankingStrategy.scopeLimits; if (!scopeLimits) throw new Error("expected claude scopeLimits"); expect(scopeLimits(report).map(limit => limit.id)).toEqual(["anthropic:5h", "anthropic:7d"]); diff --git a/packages/ai/test/cursor-exec-handlers.test.ts b/packages/ai/test/cursor-exec-handlers.test.ts index 0ab77276a..9f112960b 100644 --- a/packages/ai/test/cursor-exec-handlers.test.ts +++ b/packages/ai/test/cursor-exec-handlers.test.ts @@ -1069,7 +1069,6 @@ describe("Cursor grepArgs empty-pattern guard (issue #4574)", () => { it("rejects an empty pattern with a glob-aware hint when only a glob is present", () => { const message = emptyGrepPatternRejection("", "**/*snapcompact*"); - expect(message).not.toBeNull(); expect(message).toContain("grep pattern is required"); expect(message).toContain('"**/*snapcompact*"'); expect(message).toContain("ls/read tool"); diff --git a/packages/ai/test/google-gemini-cli-alignment.test.ts b/packages/ai/test/google-gemini-cli-alignment.test.ts index baa4f3b82..b9c53b104 100644 --- a/packages/ai/test/google-gemini-cli-alignment.test.ts +++ b/packages/ai/test/google-gemini-cli-alignment.test.ts @@ -154,6 +154,7 @@ describe("Google Gemini CLI alignment", () => { expect(shouldRefreshGeminiCliCredentials).toBe(geminiCliProvider.shouldRefreshGeminiCliCredentials); expect(Object.hasOwn(geminiCliProvider, "refreshGeminiCliCredentialsIfNeeded")).toBe(false); }); + it("omits antigravity-only metadata in non-antigravity request payloads", () => { const model = createModel("google-gemini-cli"); const payload = buildRequest(model, createContext(), "proj-123", {}, false) as { @@ -367,7 +368,6 @@ describe("Google Gemini CLI alignment", () => { }).result(); expect(result.stopReason).toBe("error"); - expect(requestHeaders).toBeDefined(); expect(requestHeaders!.get("anthropic-beta")).toBe("interleaved-thinking-2025-05-14"); expect(requestHeaders!.get("X-Goog-Api-Client")).toBeNull(); expect(requestHeaders!.get("Client-Metadata")).toBeNull(); @@ -386,7 +386,6 @@ describe("Google Gemini CLI alignment", () => { fetch: fetchMock, }).result(); - expect(requestHeaders).toBeDefined(); expect(requestHeaders!.get("User-Agent")).toMatch(/^antigravity\/hub\/[0-9.]+ /); }); diff --git a/packages/ai/test/openai-codex-responses-lite.test.ts b/packages/ai/test/openai-codex-responses-lite.test.ts index ea3d12a69..fa4b5c2aa 100644 --- a/packages/ai/test/openai-codex-responses-lite.test.ts +++ b/packages/ai/test/openai-codex-responses-lite.test.ts @@ -683,7 +683,6 @@ describe("openai-codex Responses Lite and client metadata wire format", () => { }).result(); expect(result.stopReason).toBe("stop"); - expect(captured).toBeDefined(); expect(captured!.headers.get("x-openai-internal-codex-responses-lite")).toBe("true"); expect(captured!.headers.get("version")).toBe("0.144.1"); const body = captured!.body; diff --git a/packages/ai/test/openai-codex-stream.test.ts b/packages/ai/test/openai-codex-stream.test.ts index 9b79ce4bd..7e837141f 100644 --- a/packages/ai/test/openai-codex-stream.test.ts +++ b/packages/ai/test/openai-codex-stream.test.ts @@ -1425,10 +1425,7 @@ describe("openai-codex streaming", () => { // First record is the outbound request frame (the JSON we sent). const [outbound, ...inbound] = observed; - expect(outbound).toBeDefined(); expect(outbound.raw[0]).toMatch(/^: ws → /); - expect(outbound.data.length).toBeGreaterThan(0); - expect(() => JSON.parse(outbound.data)).not.toThrow(); // Inbound frames mirror the Codex response sequence emitted by `emitCodexResponse`. expect(inbound.map(e => e.event)).toEqual([ @@ -5006,10 +5003,8 @@ describe("openai-codex streaming", () => { this.scheduleOpen(); } - override send(data: string): void { + override send(_data: string): void { sendCount += 1; - const request = JSON.parse(data) as Record; - expect(typeof request.type).toBe("string"); this.emitCodexResponse({ messageId: `msg_${sendCount}`, responseId: `resp_${sendCount}`, @@ -5166,7 +5161,6 @@ describe("openai-codex streaming", () => { const toolCall = first.content.find( (c): c is Extract<(typeof first.content)[number], { type: "toolCall" }> => c.type === "toolCall", ); - expect(toolCall).toBeDefined(); const toolResult = { role: "toolResult" as const, toolCallId: toolCall!.id, @@ -5257,7 +5251,6 @@ describe("openai-codex streaming", () => { const toolCall = first.content.find( (c): c is Extract<(typeof first.content)[number], { type: "toolCall" }> => c.type === "toolCall", ); - expect(toolCall).toBeDefined(); const toolResult = { role: "toolResult" as const, toolCallId: toolCall!.id, diff --git a/packages/ai/test/openai-completions-compat.test.ts b/packages/ai/test/openai-completions-compat.test.ts index c99ff05c4..d8bebd5d1 100644 --- a/packages/ai/test/openai-completions-compat.test.ts +++ b/packages/ai/test/openai-completions-compat.test.ts @@ -242,11 +242,9 @@ describe("openai-completions compatibility", () => { }; const messages = convertMessages(model, { messages: [assistantMessage] }, compat); const assistant = messages.find(message => message.role === "assistant"); - expect(assistant).toBeDefined(); if (assistant?.role !== "assistant") { throw new Error("assistant message missing"); } - expect(typeof assistant.content).toBe("string"); // Ordinary adjacent text blocks (bridge stitching, imported transcripts, // streaming chunk splits) preserve their original byte sequence on // flatten. The demoted-thinking separator is inserted by the flatten @@ -289,11 +287,9 @@ describe("openai-completions compatibility", () => { }, ); const assistant = messages.find(message => message.role === "assistant"); - expect(assistant).toBeDefined(); if (assistant?.role !== "assistant") throw new Error("assistant message missing"); // Regression: thinking+text replay used to call `.unshift` on the string // content set above (TypeError). Both blocks must survive as one string. - expect(typeof assistant.content).toBe("string"); expect(assistant.content).toBe(`${renderDemotedThinking(model.id, "chain of thought")} final answer`); }); @@ -328,7 +324,6 @@ describe("openai-completions compatibility", () => { }, ); const assistant = messages.find(message => message.role === "assistant"); - expect(assistant).toBeDefined(); if (assistant?.role !== "assistant") throw new Error("assistant message missing"); expect(assistant.content).toBe(renderDemotedThinking(model.id, "only thoughts")); }); @@ -572,7 +567,6 @@ describe("openai-completions compatibility", () => { // block is present, and Fireworks was previously on the multi-system // allowlist. The bundled entry must auto-detect single-system. const model = getBundledModel<"openai-completions">("fireworks", "qwen3.7-plus"); - expect(model.compat.supportsMultipleSystemMessages).toBe(false); const messages = convertMessages( model, @@ -1079,9 +1073,7 @@ describe("openai-completions compatibility", () => { const compat = { ...model.compat, requiresReasoningContentForToolCalls: true }; const messages = convertMessages(model, { messages: [result] }, compat); const assistant = messages.find(message => message.role === "assistant"); - expect(assistant).toBeDefined(); const assistantObject = toObject(assistant); - expect(assistantObject).toBeDefined(); expect(assistantObject?.reasoning_text).toBe("inspect tool output"); expect(assistantObject?.reasoning_content).toBeUndefined(); }); @@ -1322,7 +1314,6 @@ describe("kimi model detection via detectCompat", () => { const messages = convertMessages(model, { messages: [toolCallMessage] }, compat); const assistant = messages.find(m => m.role === "assistant"); const assistantObject = toObject(assistant); - expect(assistantObject).toBeDefined(); if (!assistantObject) { throw new Error("assistant message missing"); } @@ -1401,7 +1392,6 @@ describe("kimi model detection via detectCompat", () => { const payload = (await promise) as { messages: Array> }; const assistant = payload.messages.find(m => m.role === "assistant"); - expect(assistant).toBeDefined(); expect(assistant?.reasoning_content).toBe("Need to read the file before answering."); // The streamed `reasoning` key must NOT land in the wire body alongside // `reasoning_content`; opencode's strict schema rejects unknown fields. @@ -1470,7 +1460,6 @@ describe("kimi model detection via detectCompat", () => { const payload = (await promise) as { messages: Array> }; const assistant = payload.messages.find(m => m.role === "assistant"); - expect(assistant).toBeDefined(); expect(assistant?.content).toBe(renderDemotedThinking(model.id, "Need to preserve cross-api reasoning.")); expect(assistant?.reasoning_content).toBe(""); expect(assistant?.reasoning).toBeUndefined(); @@ -1718,7 +1707,6 @@ describe("kimi model detection via detectCompat", () => { tool_choice?: unknown; }; const assistant = payload.messages.find(m => m.role === "assistant"); - expect(assistant).toBeDefined(); expect(assistant?.reasoning_content).toBe("Plan first, then call the tool."); expect(payload.reasoning_effort).toBe("high"); expect(payload.tool_choice).toBe("auto"); @@ -1881,7 +1869,6 @@ describe("kimi model detection via detectCompat", () => { const payload = (await promise) as { messages: Array> }; const assistant = payload.messages.find(m => m.role === "assistant"); - expect(assistant).toBeDefined(); expect(assistant?.reasoning_content).toBe("Need to read the file before answering."); // DeepSeek's allowsSynthetic=false must keep the stale `reasoning` key // off the wire body so opencode's schema validation does not flag it. @@ -2053,7 +2040,6 @@ describe("kimi model detection via detectCompat", () => { expect(compat.requiresReasoningContentForToolCalls).toBe(true); const messages = convertMessages(model, { messages: [toolCallMessage] }, compat); const assistant = messages.find(m => m.role === "assistant"); - expect(assistant).toBeDefined(); expect(toObject(assistant)?.reasoning_content).toBe("."); }); diff --git a/packages/ai/test/openai-tool-strict-mode.test.ts b/packages/ai/test/openai-tool-strict-mode.test.ts index f7d9a8081..c4ad4c7ae 100644 --- a/packages/ai/test/openai-tool-strict-mode.test.ts +++ b/packages/ai/test/openai-tool-strict-mode.test.ts @@ -853,7 +853,6 @@ describe("OpenAI tool strict mode", () => { tools?: Array<{ strict?: boolean }>; }; - expect(model.compat.supportsStrictMode).toBe(true); expect(payload.tools?.[0]?.strict).toBe(false); }); @@ -878,7 +877,6 @@ describe("OpenAI tool strict mode", () => { tools?: Array<{ strict?: boolean }>; }; - expect(model.compat.supportsStrictMode).toBe(true); expect(payload.tools?.[0]?.strict).toBe(true); }); diff --git a/packages/ai/test/schema-normalization.test.ts b/packages/ai/test/schema-normalization.test.ts index 58d5d3da7..4e5f87b03 100644 --- a/packages/ai/test/schema-normalization.test.ts +++ b/packages/ai/test/schema-normalization.test.ts @@ -1014,7 +1014,6 @@ describe("normalizeSchemaForCCA", () => { }; (circular.properties as Record).self = circular; - expect(() => normalizeSchemaForCCA(circular)).not.toThrow(); expect(normalizeSchemaForCCA(circular)).toEqual({ type: "object", properties: { diff --git a/packages/ai/test/stream-markup-healing.test.ts b/packages/ai/test/stream-markup-healing.test.ts index f9e59f421..6e79b17ce 100644 --- a/packages/ai/test/stream-markup-healing.test.ts +++ b/packages/ai/test/stream-markup-healing.test.ts @@ -632,8 +632,6 @@ describe("Kimi K2 leaked markup healing", () => { const split = "<|tool_ca"; const a = full.slice(0, full.indexOf(split) + split.length); const b = full.slice(a.length); - expect(a + b).toBe(full); - expect(a.endsWith("<|tool_ca")).toBe(true); const fetchMock = mockFetch([ chunk(model.id, { content: a }), @@ -1078,7 +1076,6 @@ describe("OpenAI completions provider DSML envelope healing", () => { it("heals NanoGPT-hosted DeepSeek V4 Pro DSML leaks (issue #1488)", async () => { const model = getBundledModel<"openai-completions">("nanogpt", "deepseek/deepseek-v4-pro"); - expect(model.provider).toBe("nanogpt"); let payload: Record | undefined; const fetchMock = mockFetch([ diff --git a/packages/ai/test/stream.test.ts b/packages/ai/test/stream.test.ts index 63caa3c76..0add12576 100644 --- a/packages/ai/test/stream.test.ts +++ b/packages/ai/test/stream.test.ts @@ -57,7 +57,6 @@ async function basicTextGeneration(model: Model, options const response = await complete(model, context, options); expect(response.role).toBe("assistant"); - expect(response.content).toBeTruthy(); expect(response.usage.input + response.usage.cacheRead).toBeGreaterThan(0); expect(response.usage.output).toBeGreaterThan(0); expect(response.errorMessage).toBeFalsy(); @@ -69,7 +68,6 @@ async function basicTextGeneration(model: Model, options const secondResponse = await complete(model, context, options); expect(secondResponse.role).toBe("assistant"); - expect(secondResponse.content).toBeTruthy(); expect(secondResponse.usage.input + secondResponse.usage.cacheRead).toBeGreaterThan(0); expect(secondResponse.usage.output).toBeGreaterThan(0); expect(secondResponse.errorMessage).toBeFalsy(); @@ -260,7 +258,6 @@ async function handleImage(model: Model, options?: Optio const response = await complete(model, context, options); // Check the response mentions red and circle - expect(response.content.length > 0).toBeTruthy(); const textContent = response.content.find(b => b.type === "text"); if (textContent && textContent.type === "text") { const lowerContent = textContent.text.toLowerCase(); @@ -348,7 +345,6 @@ async function multiTurn(model: Model, options?: Options expect(hasSeenThinking || hasSeenToolCalls).toBe(true); // The accumulated text should reference both calculations - expect(allTextContent).toBeTruthy(); expect(allTextContent.includes("714")).toBe(true); expect(allTextContent.includes("887")).toBe(true); } @@ -537,7 +533,6 @@ describe("Generate E2E Tests", () => { ); expect(response.stopReason).toBe("aborted"); - expect(response.errorMessage).toBeTruthy(); expect(response.errorMessage).not.toContain("Vertex AI requires a project ID"); expect(response.errorMessage).not.toContain("Vertex AI requires a location"); } finally { @@ -1005,42 +1000,6 @@ describe("Generate E2E Tests", () => { ); }); - describe.skipIf(!e2eApiKey("OPENAI_API_KEY"))("OpenAI Responses Provider (gpt-5-mini)", () => { - const model = getBundledModel("openai", "gpt-5-mini") as Model<"openai-responses">; - - it( - "should complete basic text generation", - async () => { - await basicTextGeneration(model); - }, - { retry: 3 }, - ); - - it( - "should handle tool calling", - async () => { - await handleToolCall(model); - }, - { retry: 3 }, - ); - - it( - "should handle streaming", - async () => { - await handleStreaming(model); - }, - { retry: 3 }, - ); - - it( - "should handle image input", - async () => { - await handleImage(model); - }, - { retry: 3 }, - ); - }); - describe.skipIf(!e2eApiKey("XAI_API_KEY"))("xAI Provider (grok-code-fast-1 via OpenAI Completions)", () => { const llm = getBundledModel("xai", "grok-code-fast-1"); @@ -1350,16 +1309,6 @@ describe("Generate E2E Tests", () => { { retry: 3 }, ); - it( - "should handle thinking mode", - async () => { - // FIXME Skip for now, getting a 422 status code, need to test with official SDK - // const llm = getModel("mistral", "magistral-medium-latest"); - // await handleThinking(llm, { reasoningEffort: "medium" }); - }, - { retry: 3 }, - ); - it( "should handle multi-turn with thinking and tools", async () => { @@ -1783,7 +1732,6 @@ describe("Generate E2E Tests", () => { ); expect(response.stopReason, `Error: ${response.errorMessage}`).not.toBe("error"); - expect(capturedPayload).toBeTruthy(); const payload = capturedPayload as { additionalModelRequestFields?: { diff --git a/packages/ai/test/tool-argument-coercion.test.ts b/packages/ai/test/tool-argument-coercion.test.ts index 1adac6b47..e83c092b5 100644 --- a/packages/ai/test/tool-argument-coercion.test.ts +++ b/packages/ai/test/tool-argument-coercion.test.ts @@ -20,7 +20,6 @@ describe("Tool argument coercion", () => { const result = validateToolArguments(tool, toolCall) as { timeout: number }; expect(result.timeout).toBe(300); - expect(typeof result.timeout).toBe("number"); }); it("preserves string values when schema expects string", () => { @@ -39,7 +38,6 @@ describe("Tool argument coercion", () => { const result = validateToolArguments(tool, toolCall) as { label: string }; expect(result.label).toBe("300"); - expect(typeof result.label).toBe("string"); }); it("stringifies object values when schema expects string", () => { @@ -1057,7 +1055,6 @@ describe("Tool argument coercion", () => { }; const result = validateToolArguments(tool, toolCall); expect(result.tick_size).toBe(1); - expect(typeof result.tick_size).toBe("number"); }); it("leaves Optional as undefined when absent", () => { @@ -1075,6 +1072,7 @@ describe("Tool argument coercion", () => { const result = validateToolArguments(tool, toolCall); expect(result.tick_size).toBeUndefined(); }); + it("strips string 'null' on optional boolean field", () => { const tool: Tool = { name: "edit-tool", @@ -1311,7 +1309,6 @@ describe("Tool argument coercion", () => { // which `JSON.parse` rejects unless the control char is escaped. const stringifiedPhases = '[{"name":"Investigation","tasks":[{"content":"Locate code","details":"line one\nline two"}]}]'; - expect(stringifiedPhases.includes("\n")).toBe(true); const toolCall: ToolCall = { type: "toolCall", diff --git a/packages/catalog/test/github-copilot-model-limits.test.ts b/packages/catalog/test/github-copilot-model-limits.test.ts index fae000eae..9867b2c0a 100644 --- a/packages/catalog/test/github-copilot-model-limits.test.ts +++ b/packages/catalog/test/github-copilot-model-limits.test.ts @@ -52,9 +52,7 @@ async function discoverCopilotModels( }); }); const options = githubCopilotModelManagerOptions({ apiKey, fetch: fetchMock }); - expect(options.fetchDynamicModels).toBeDefined(); const models = await options.fetchDynamicModels?.(); - expect(models).not.toBeNull(); return { models: models ?? [], fetchMock, requestApiVersions }; } @@ -112,7 +110,7 @@ describe("github copilot model limits mapping", () => { }); it("uses max_context_window_tokens as context window when Copilot reports a prompt budget", async () => { - const { models, fetchMock } = await discoverCopilotModels({ + const { models } = await discoverCopilotModels({ data: [ { id: "gemini-2.5-pro", @@ -129,10 +127,8 @@ describe("github copilot model limits mapping", () => { }); const model = models.find(candidate => candidate.id === "gemini-2.5-pro"); - expect(model).toBeDefined(); expect(model?.contextWindow).toBe(1_048_576); expect(model?.maxTokens).toBe(64_000); - expect(fetchMock).toHaveBeenCalledTimes(1); }); it("falls back to explicit context_length and derives max tokens from max_output_tokens", async () => { @@ -154,7 +150,6 @@ describe("github copilot model limits mapping", () => { }); const model = models.find(candidate => candidate.id === "gpt-5.2-codex"); - expect(model).toBeDefined(); expect(model?.api).toBe("openai-responses"); expect(model?.contextWindow).toBe(250_000); expect(model?.maxTokens).toBe(128_000); @@ -177,29 +172,10 @@ describe("github copilot model limits mapping", () => { }); const model = models.find(candidate => candidate.id === "claude-opus-4.6"); - expect(model).toBeDefined(); expect(model?.contextWindow).toBe(128_000); expect(model?.maxTokens).toBe(16_000); }); - it("keeps bundled Copilot fallback limits truthful offline", () => { - expect(getBundledModel("github-copilot", "claude-opus-4.6")).toMatchObject({ - contextWindow: 168_000, - maxTokens: 32_000, - }); - expect(getBundledModel("github-copilot", "gpt-5.2")).toMatchObject({ - contextWindow: 272_000, - maxTokens: 128_000, - }); - expect(getBundledModel("github-copilot", "gpt-5.4-mini")).toMatchObject({ - contextWindow: 272_000, - maxTokens: 128_000, - }); - expect(getBundledModel("github-copilot", "grok-code-fast-1")).toMatchObject({ - contextWindow: 192_000, - maxTokens: 64_000, - }); - }); it("inherits bundled GPT-5.4 mini reasoning metadata during discovery", async () => { const { models } = await discoverCopilotModels({ data: [ @@ -220,7 +196,6 @@ describe("github copilot model limits mapping", () => { }); const model = models.find(candidate => candidate.id === "gpt-5.4-mini"); - expect(model).toBeDefined(); expect(model?.api).toBe("openai-responses"); expect(model?.reasoning).toBe(true); // max_context_window_tokens is the model window; max_prompt_tokens is only @@ -251,7 +226,6 @@ describe("github copilot model limits mapping", () => { }); const model = models.find(candidate => candidate.id === "gpt-5.4"); - expect(model).toBeDefined(); expect(model?.contextWindow).toBe(400_000); expect(model?.maxTokens).toBe(128_000); }); @@ -293,7 +267,6 @@ describe("github copilot model limits mapping", () => { const model = models.find(candidate => candidate.id === "gpt-5.4"); expect(getBundledModel("github-copilot", "gpt-5.4")?.contextWindow).toBe(272_000); - expect(model).toBeDefined(); expect(model?.contextWindow).toBe(400_000); expect(model?.maxTokens).toBe(128_000); expect(model?.reasoning).toBe(true); @@ -314,7 +287,6 @@ describe("github copilot model limits mapping", () => { }); const model = models.find(candidate => candidate.id === "gpt-5.4"); - expect(model).toBeDefined(); // Should use the Copilot-specific bundled reference (272k after models.json fix), // not the OpenAI global reference (1050k). expect(model?.contextWindow).toBe(272_000); @@ -332,7 +304,6 @@ describe("github copilot model limits mapping", () => { }); const model = models.find(candidate => candidate.id === "mai-code-1-flash-picker"); - expect(model).toBeDefined(); expect(model?.api).toBe("openai-responses"); }); it("routes grok-4.5 to the openai-responses endpoint (#7096)", async () => { @@ -346,7 +317,6 @@ describe("github copilot model limits mapping", () => { }); const model = models.find(candidate => candidate.id === "grok-4.5"); - expect(model).toBeDefined(); expect(model?.api).toBe("openai-responses"); }); for (const migration of [ @@ -512,7 +482,6 @@ describe("github copilot tiered context windows", () => { }); const base = models.find(candidate => candidate.id === "claude-opus-4.7"); - expect(base).toBeDefined(); expect(base?.api).toBe("anthropic-messages"); expect(base?.contextWindow).toBe(264_000); expect(base?.maxTokens).toBe(64_000); @@ -520,7 +489,6 @@ describe("github copilot tiered context windows", () => { expect(base?.headers?.["X-GitHub-Api-Version"]).toBe("2026-06-01"); const variant = models.find(candidate => candidate.id === "claude-opus-4.7-1m"); - expect(variant).toBeDefined(); expect(variant?.requestModelId).toBe("claude-opus-4.7"); expect(variant?.name).toBe("Claude Opus 4.7 (1M)"); expect(variant?.api).toBe("anthropic-messages"); @@ -546,7 +514,6 @@ describe("github copilot tiered context windows", () => { }); const variant = models.find(candidate => candidate.id === "gemini-9.9-pro-preview-1m"); - expect(variant).toBeDefined(); expect(variant?.cost).toEqual({ input: 4, output: 18, cacheRead: 0.4, cacheWrite: 0 }); }); diff --git a/packages/catalog/test/gitlab-duo-workflow-discovery.test.ts b/packages/catalog/test/gitlab-duo-workflow-discovery.test.ts index 8a586ac8a..f22fd9264 100644 --- a/packages/catalog/test/gitlab-duo-workflow-discovery.test.ts +++ b/packages/catalog/test/gitlab-duo-workflow-discovery.test.ts @@ -12,7 +12,6 @@ import { import { getSupportedEfforts } from "@oh-my-pi/pi-catalog/model-thinking"; import { isCatalogDescriptor } from "@oh-my-pi/pi-catalog/provider-models/descriptor-types"; import { PROVIDER_DESCRIPTORS } from "@oh-my-pi/pi-catalog/provider-models/descriptors"; -import { gitLabDuoWorkflowModelManagerOptions } from "@oh-my-pi/pi-catalog/provider-models/special"; import type { FetchImpl } from "@oh-my-pi/pi-catalog/types"; const TEST_TOKEN = "redacted-test-token"; @@ -509,25 +508,9 @@ describe("GitLab Duo Workflow discovery", () => { }); it("marks models as non-reasoning so the thinking-effort selector stays hidden", () => { const spec = buildGitLabDuoWorkflowModelSpec({ name: "Opus", ref: "claude_opus_4_8" }); - expect(spec.reasoning).toBe(false); expect(getSupportedEfforts(spec)).toEqual([]); }); - it("seeds the fallback model as a static catalog entry so a fresh install surfaces a default", () => { - // The generator bundles this descriptor's static model into models.json, and the - // runtime manager exposes it before any credentialed dynamic discovery runs. Both - // the fresh-install bundle and the pre-discovery runtime list depend on this seed, - // so assert the descriptor (not the bundled JSON) carries the fallback model. - const options = gitLabDuoWorkflowModelManagerOptions(); - expect(options.providerId).toBe("gitlab-duo-agent"); - expect(options.dynamicModelsAuthoritative).toBe(true); - expect(options.staticModels?.map(model => model.id)).toEqual(["claude_sonnet_4_6_vertex"]); - const seed = options.staticModels?.[0]; - expect(seed?.provider).toBe("gitlab-duo-agent"); - expect(seed?.api).toBe("gitlab-duo-agent"); - expect(seed?.reasoning).toBe(false); - }); - it("keeps the gitlab-duo-agent descriptor out of catalog generation discovery", () => { // The descriptor must NOT carry `catalogDiscovery`: that field is the sole gate // for the generator's discovery loop (`isCatalogDescriptor`). Were it present, @@ -545,8 +528,6 @@ describe("GitLab Duo Workflow discovery", () => { it("seeds a namespace-free fallback model carrying no account-scoped namespace id", () => { // The bundled seed must never leak the generating machine's root namespace. const seed = buildGitLabDuoWorkflowFallbackModel(); - expect(seed.id).toBe("claude_sonnet_4_6_vertex"); - expect(seed.provider).toBe("gitlab-duo-agent"); expect(seed).not.toHaveProperty("gitlabDuoWorkflowRootNamespaceId"); // A credentialed runtime discovery, by contrast, pins the namespace it resolved. const scoped = buildGitLabDuoWorkflowModelSpec( diff --git a/packages/catalog/test/model-thinking.test.ts b/packages/catalog/test/model-thinking.test.ts index 926ee93a9..908bd2c36 100644 --- a/packages/catalog/test/model-thinking.test.ts +++ b/packages/catalog/test/model-thinking.test.ts @@ -52,20 +52,6 @@ describe("model thinking derivation", () => { expect(() => requireSupportedEffort(model, Effort.XHigh)).toThrow(/Supported efforts: medium, high/); }); - it("stores xhigh support directly in metadata for GPT-5.2", () => { - const model = createModel({ - id: "gpt-5.2-codex", - api: "openai-codex-responses", - provider: "openai-codex", - }); - - expect(model.thinking).toEqual({ - mode: "effort", - efforts: [Effort.Low, Effort.Medium, Effort.High, Effort.XHigh], - }); - expect(requireSupportedEffort(model, Effort.XHigh)).toBe(Effort.XHigh); - }); - it("stores MiniMax M2 and GPT-OSS OpenAI-compatible effort limits in model metadata", () => { const minimax = createModel({ id: "minimax-m2.7", @@ -136,7 +122,6 @@ describe("model thinking derivation", () => { expect(mimo.compat.reasoningEffortMap).toEqual({ minimal: "low", xhigh: "high" }); expect(openRouterMimo.compat.reasoningEffortMap).toEqual({ minimal: "low", xhigh: "high" }); expect(staleMimo.compat.reasoningEffortMap).toEqual({ minimal: "low", xhigh: "high" }); - expect(requireSupportedEffort(mimo, Effort.High)).toBe(Effort.High); expect(() => requireSupportedEffort(mimo, Effort.XHigh)).toThrow(/Supported efforts: low, medium, high/); expect(clampThinkingLevelForModel(mimo, Effort.Minimal)).toBe(Effort.Low); expect(clampThinkingLevelForModel(mimo, Effort.XHigh)).toBe(Effort.High); @@ -494,25 +479,16 @@ describe("model thinking derivation", () => { // low/medium/high/max wire scale, mapped 1:1. expect(getSupportedEfforts(opus46)).toEqual([Effort.Low, Effort.Medium, Effort.High, Effort.Max]); expect(opus46.thinking?.effortMap).toBeUndefined(); - expect(mapEffortToAnthropicAdaptiveEffort(opus46, Effort.Max)).toBe("max"); expect(() => mapEffortToAnthropicAdaptiveEffort(opus46, Effort.XHigh)).toThrow(/not supported/); // Opus 4.7+ on the Messages API exposes the full five-tier wire scale // low..max with no remapping. expect(getSupportedEfforts(opus47)).toEqual([Effort.Low, Effort.Medium, Effort.High, Effort.XHigh, Effort.Max]); expect(opus47.thinking?.effortMap).toBeUndefined(); - expect(mapEffortToAnthropicAdaptiveEffort(opus47, Effort.Low)).toBe("low"); - expect(mapEffortToAnthropicAdaptiveEffort(opus47, Effort.High)).toBe("high"); - expect(mapEffortToAnthropicAdaptiveEffort(opus47, Effort.XHigh)).toBe("xhigh"); - expect(mapEffortToAnthropicAdaptiveEffort(opus47, Effort.Max)).toBe("max"); expect(() => mapEffortToAnthropicAdaptiveEffort(opus47, Effort.Minimal)).toThrow(/not supported/); expect(mapEffortToAnthropicAdaptiveEffort(mythos, Effort.XHigh)).toBe("xhigh"); - expect(mapEffortToAnthropicAdaptiveEffort(sonnet5, Effort.Max)).toBe("max"); // Bedrock Converse stays on the four-tier scale regardless of version. expect(getSupportedEfforts(opus47Bedrock)).toEqual([Effort.Low, Effort.Medium, Effort.High, Effort.Max]); expect(opus47Bedrock.thinking?.effortMap).toBeUndefined(); - expect(mapEffortToAnthropicAdaptiveEffort(opus47Bedrock, Effort.High)).toBe("high"); - expect(mapEffortToAnthropicAdaptiveEffort(opus47Bedrock, Effort.Max)).toBe("max"); - expect(mapEffortToAnthropicAdaptiveEffort(sonnet5Bedrock, Effort.Max)).toBe("max"); expect(() => mapEffortToAnthropicAdaptiveEffort(sonnet5Bedrock, Effort.XHigh)).toThrow(/not supported/); // Sonnet 4.6 runs adaptive mode on the three-tier low/medium/high scale. expect(getSupportedEfforts(sonnet46)).toEqual([Effort.Low, Effort.Medium, Effort.High]); @@ -770,7 +746,6 @@ describe("model thinking runtime helpers", () => { expect(model.thinking).toEqual({ mode: "effort", efforts: [Effort.Medium, Effort.High], requiresEffort: true }); expect(clampThinkingLevelForModel(model, Effort.Minimal)).toBe(Effort.Medium); expect(clampThinkingLevelForModel(model, Effort.XHigh)).toBe(Effort.High); - expect(clampThinkingLevelForModel(model, Effort.High)).toBe(Effort.High); }); it('forces "off" for non-reasoning models', () => { @@ -784,17 +759,6 @@ describe("model thinking runtime helpers", () => { expect(clampThinkingLevelForModel(model, Effort.High)).toBeUndefined(); }); - it("enables xhigh for openai-completions API (custom models)", () => { - const model = createModel({ - id: "custom-model", - api: "openai-completions", - provider: "custom", - }); - - expect(model.thinking?.efforts.at(-1)).toBe(Effort.XHigh); - expect(requireSupportedEffort(model, Effort.XHigh)).toBe(Effort.XHigh); - }); - it("does not expose xhigh for binary-thinking openai-compat transports", () => { const model = createModel({ id: "glm-4.7", @@ -808,7 +772,6 @@ describe("model thinking runtime helpers", () => { mode: "effort", efforts: [Effort.Minimal, Effort.Low, Effort.Medium, Effort.High], }); - expect(requireSupportedEffort(model, Effort.High)).toBe(Effort.High); expect(() => requireSupportedEffort(model, Effort.XHigh)).toThrow( /Supported efforts: minimal, low, medium, high/, ); @@ -827,7 +790,6 @@ describe("model thinking runtime helpers", () => { mode: "effort", efforts: [Effort.High, Effort.Max], }); - expect(requireSupportedEffort(model, Effort.Max)).toBe(Effort.Max); expect(() => requireSupportedEffort(model, Effort.XHigh)).toThrow(/Supported efforts: high, max/); // Selecting a retired tier clamps down instead of erroring in UI flows. expect(clampThinkingLevelForModel(model, Effort.XHigh)).toBe(Effort.High); @@ -845,8 +807,6 @@ describe("model thinking runtime helpers", () => { mode: "effort", efforts: [Effort.High, Effort.Max], }); - expect(requireSupportedEffort(model, Effort.High)).toBe(Effort.High); - expect(requireSupportedEffort(model, Effort.Max)).toBe(Effort.Max); expect(() => requireSupportedEffort(model, Effort.Medium)).toThrow(/Supported efforts: high, max/); }); @@ -863,7 +823,6 @@ describe("model thinking runtime helpers", () => { mode: "effort", efforts: [Effort.Minimal, Effort.Low, Effort.Medium, Effort.High], }); - expect(requireSupportedEffort(model, Effort.High)).toBe(Effort.High); expect(() => requireSupportedEffort(model, Effort.XHigh)).toThrow( /Supported efforts: minimal, low, medium, high/, ); @@ -894,21 +853,9 @@ describe("model thinking runtime helpers", () => { expect(opus46.thinking?.efforts).toEqual([Effort.Low, Effort.Medium, Effort.High, Effort.Max]); expect(sonnet46.thinking?.efforts.at(-1)).toBe(Effort.High); expect(sonnet5.thinking?.efforts.at(-1)).toBe(Effort.Max); - expect(requireSupportedEffort(fable, Effort.Max)).toBe(Effort.Max); - expect(requireSupportedEffort(sonnet5, Effort.XHigh)).toBe(Effort.XHigh); expect(() => requireSupportedEffort(opus46, Effort.XHigh)).toThrow(/not supported/); }); - it("enables xhigh for openai-responses and openai-codex-responses APIs", () => { - const responsesModel = createModel({ id: "custom-responses", api: "openai-responses", provider: "custom" }); - const codexModel = createModel({ id: "custom-codex", api: "openai-codex-responses", provider: "custom" }); - - expect(responsesModel.thinking?.efforts.at(-1)).toBe(Effort.XHigh); - expect(codexModel.thinking?.efforts.at(-1)).toBe(Effort.XHigh); - expect(requireSupportedEffort(responsesModel, Effort.XHigh)).toBe(Effort.XHigh); - expect(requireSupportedEffort(codexModel, Effort.XHigh)).toBe(Effort.XHigh); - }); - it("rejects effort requests against un-built reasoning specs", () => { const spec = { id: "broken-reasoner", diff --git a/packages/coding-agent/test/acp-agent.test.ts b/packages/coding-agent/test/acp-agent.test.ts index 859341530..f680b6b1b 100644 --- a/packages/coding-agent/test/acp-agent.test.ts +++ b/packages/coding-agent/test/acp-agent.test.ts @@ -661,7 +661,6 @@ describe("ACP agent", () => { await harness.agent.setSessionMode({ sessionId: created.sessionId, modeId: "plan" }); const handler = session.planProposalHandler; - expect(typeof handler).toBe("function"); // No plan file written → handler surfaces a ToolError telling the // agent to write the plan before requesting approval. diff --git a/packages/coding-agent/test/acp-builtins.test.ts b/packages/coding-agent/test/acp-builtins.test.ts index 825e7920d..bd8653e7c 100644 --- a/packages/coding-agent/test/acp-builtins.test.ts +++ b/packages/coding-agent/test/acp-builtins.test.ts @@ -1085,8 +1085,7 @@ describe("wave 5 — adapters and polish", () => { // Without this assertion, the command could succeed via a side-effect-free // path that prints the success message without writing the host config. expect(spy).toHaveBeenCalledTimes(1); - const [configPath, name, hostConfig] = spy.mock.calls[0]!; - expect(typeof configPath).toBe("string"); + const [, name, hostConfig] = spy.mock.calls[0]!; expect(name).toBe("foo"); expect(hostConfig).toMatchObject({ host: "x", username: "y" }); } finally { diff --git a/packages/coding-agent/test/advisor/advisor.test.ts b/packages/coding-agent/test/advisor/advisor.test.ts index b4f1a6f3b..ae7b5205f 100644 --- a/packages/coding-agent/test/advisor/advisor.test.ts +++ b/packages/coding-agent/test/advisor/advisor.test.ts @@ -6,7 +6,6 @@ import * as AIError from "@oh-my-pi/pi-ai/error"; import { kCursorExecResolved } from "@oh-my-pi/pi-ai/utils/block-symbols"; import type { TUI } from "@oh-my-pi/pi-tui"; import { - ADVISOR_DEFAULT_TOOL_NAMES, AdviseTool, type AdvisorAgent, type AdvisorNote, @@ -33,7 +32,6 @@ import { getThemeByName, setThemeInstance } from "../../src/modes/theme/theme"; import { SecretObfuscator } from "../../src/secrets/obfuscator"; import { formatSessionHistoryMarkdown } from "../../src/session/session-history-format"; import { YieldQueue } from "../../src/session/yield-queue"; -import { BUILTIN_TOOL_NAMES } from "../../src/tools/builtin-names"; /** Poll until the drain loop reaches the asserted state — waitForCatchup * releases IMMEDIATELY on advisor failure (the primary must never park on a @@ -96,7 +94,6 @@ describe("advisor", () => { content: "Use `bun check`, never `tsc`.\nNo `any` unless absolutely necessary.", }, ]); - expect(rendered).toBeDefined(); expect(rendered).toContain(''); // Content is injected verbatim (noEscape) so backticks/markup survive for the model. expect(rendered).toContain("Use `bun check`, never `tsc`."); @@ -2364,7 +2361,7 @@ describe("advisor", () => { expect(promptInputs).toHaveLength(1); messages = [{ role: "user", content: "a", timestamp: 1 } as AgentMessage]; - expect(() => runtime.onTurnEnd()).not.toThrow(); + runtime.onTurnEnd(); expect(promptInputs).toHaveLength(1); }); @@ -3261,7 +3258,7 @@ describe("advisor", () => { timestamp: 2, } as AgentMessage; messages.push(poisoned); - expect(() => runtime.onTurnEnd(messages)).not.toThrow(); + runtime.onTurnEnd(messages); // A parked primary must not wait out the catch-up budget. const started = performance.now(); await runtime.waitForCatchup(60_000, 1); @@ -5370,21 +5367,6 @@ describe("advisor", () => { }); }); - describe("advisor default tools", () => { - it("defaults to read/grep/glob, a subset of the full grantable tool pool", () => { - expect([...ADVISOR_DEFAULT_TOOL_NAMES]).toEqual(["read", "grep", "glob"]); - // The advisor is a full agent now: every built tool is grantable (no hard - // read-only restriction), including mutating ones like edit/bash/write. - const builtin = new Set(BUILTIN_TOOL_NAMES); - for (const name of ["read", "grep", "glob", "edit", "bash", "write"]) { - expect(builtin.has(name)).toBe(true); - } - for (const name of ADVISOR_DEFAULT_TOOL_NAMES) { - expect(builtin.has(name)).toBe(true); - } - }); - }); - describe("createAdvisorMessageCard", () => { const strip = (lines: readonly string[]): string => lines.join("\n").replace(/\x1b\[[0-9;]*m/g, ""); diff --git a/packages/coding-agent/test/agent-hub-activate.test.ts b/packages/coding-agent/test/agent-hub-activate.test.ts index bdde6e85b..62a4ef9cc 100644 --- a/packages/coding-agent/test/agent-hub-activate.test.ts +++ b/packages/coding-agent/test/agent-hub-activate.test.ts @@ -470,7 +470,6 @@ describe("Agent hub Enter activation", () => { controller.showAgentHub(new SessionObserverRegistry()); - expect(capturedHub).toBeDefined(); expect(focusTargets[0]).toBe(capturedHub); capturedHub!.handleInput("\r"); @@ -588,7 +587,6 @@ describe("Agent hub double-← gating", () => { expect(shown()).toBeUndefined(); const shownHub = await shownReady; - expect(shownHub).toBeDefined(); expect(agents.get("Worker")?.sessionFile).toBe(workerSessionFile); shownHub!.dispose(); }); diff --git a/packages/coding-agent/test/agent-hub-ordering.test.ts b/packages/coding-agent/test/agent-hub-ordering.test.ts index e375f506b..939330307 100644 --- a/packages/coding-agent/test/agent-hub-ordering.test.ts +++ b/packages/coding-agent/test/agent-hub-ordering.test.ts @@ -230,7 +230,6 @@ describe("Agent hub row ordering", () => { expect(visibleIds).toHaveLength(2); expect(getSessions).not.toHaveBeenCalled(); expect(getSession.mock.calls.length).toBeLessThanOrEqual(8); - expect(getSession.mock.calls.length).toBeGreaterThan(0); const text = Bun.stripANSI(hub.render(120).join("\n")); expect(text).toContain("10000 parked"); @@ -241,7 +240,6 @@ describe("Agent hub row ordering", () => { getSession.mockClear(); hub.handleInput("j"); const afterMove = renderedAgentIds(hub); - expect(afterMove.length).toBeGreaterThan(0); expect(afterMove.length).toBeLessThanOrEqual(2); expect(afterMove).toContain(visibleIds[1]!); expect(getSessions).not.toHaveBeenCalled(); @@ -296,7 +294,6 @@ describe("Agent hub row ordering", () => { expect(getSession.mock.calls.length).toBeLessThanOrEqual(6); const text = Bun.stripANSI(hub.render(120).join("\n")); expect(text).toContain("task for"); - expect(text).toContain(visibleIds[0]!); } finally { hub.dispose(); } @@ -633,7 +630,6 @@ describe("Agent hub row ordering", () => { expect(rendered).toContain("Flat"); expect(rendered).toContain("By parent"); expect(rendered).toContain("$0.213 · 2m14s active · 12 req · 27 tools · 18K tok"); - expect(rendered).toContain("Security Reviewer"); expect(rendered).toContain("read · src/session/agent-session.ts"); expect(rendered).toContain("31K/128K 24%"); const createdDate = new Date(createdAt); diff --git a/packages/coding-agent/test/agent-session-acp-permission.test.ts b/packages/coding-agent/test/agent-session-acp-permission.test.ts index 09b3dd1d2..b9aac36bf 100644 --- a/packages/coding-agent/test/agent-session-acp-permission.test.ts +++ b/packages/coding-agent/test/agent-session-acp-permission.test.ts @@ -179,7 +179,6 @@ it("allow_once: calls bridge once and executes the underlying tool", async () => await session.setActiveToolsByName(["bash"]); // Get the wrapped tool from the agent's active set. const wrappedBash = session.agent.state.tools.find(t => t.name === "bash"); - expect(wrappedBash).toBeDefined(); await wrappedBash!.execute("call-1", { command: "echo hi" }, undefined, undefined as never, undefined as never); @@ -195,7 +194,6 @@ it("explicit yolo approval mode skips the ACP permission gate", async () => { await session.setActiveToolsByName(["bash"]); const wrappedBash = session.agent.state.tools.find(t => t.name === "bash"); - expect(wrappedBash).toBeDefined(); await wrappedBash!.execute("call-1", { command: "echo hi" }, undefined, undefined as never, undefined as never); @@ -214,7 +212,6 @@ it("explicit yolo still gates tools whose per-tool policy requires a prompt", as await session.setActiveToolsByName(["bash"]); const wrappedBash = session.agent.state.tools.find(t => t.name === "bash"); - expect(wrappedBash).toBeDefined(); await wrappedBash!.execute("call-1", { command: "echo hi" }, undefined, undefined as never, undefined as never); @@ -233,14 +230,11 @@ it("delete and move tools request ACP permission before executing", async () => return { outcome: "selected", optionId: "allow_once", kind: "allow_once" }; }, }; - const permissionSpy = spyOn(bridge, "requestPermission"); session = await createSession([deleteTool, moveTool], bridge); await session.setActiveToolsByName(["delete", "move"]); const wrappedDelete = session.agent.state.tools.find(t => t.name === "delete"); const wrappedMove = session.agent.state.tools.find(t => t.name === "move"); - expect(wrappedDelete).toBeDefined(); - expect(wrappedMove).toBeDefined(); await wrappedDelete!.execute( "call-delete", @@ -257,7 +251,6 @@ it("delete and move tools request ACP permission before executing", async () => undefined as never, ); - expect(permissionSpy).toHaveBeenCalledTimes(2); expect(requests.map(({ toolName, title, locations }) => ({ toolName, title, locations }))).toEqual([ { toolName: "delete", title: "Delete /tmp/gone.ts", locations: [{ path: "/tmp/gone.ts" }] }, { @@ -290,7 +283,6 @@ it("top-level fallback preserves ACP permission for mounted destructive tools", expect(xdev.mountedNames.has("delete")).toBe(true); expect(session.getActiveToolNames()).not.toContain("delete"); const fallbackTool = resolveMountedXdevExecutable(xdev, "delete"); - expect(fallbackTool).toBeDefined(); await fallbackTool!.execute( "call-mounted-delete", { path: "/tmp/gone.ts" }, @@ -324,13 +316,7 @@ it("startup-mounted destructive tools gain the ACP permission gate when the brid { xdev, builtInToolNames: ["read", "write"] }, ); - const dispatched = await dispatchXdevTool( - xdev, - "delete", - JSON.stringify({ path: "/tmp/gone.ts" }), - "call-startup-delete", - ); - expect(dispatched.result.isError).toBeUndefined(); + await dispatchXdevTool(xdev, "delete", JSON.stringify({ path: "/tmp/gone.ts" }), "call-startup-delete"); expect(permissionSpy).toHaveBeenCalledTimes(1); expect(deleteTool.executeCalls).toBe(1); @@ -347,9 +333,6 @@ it("edit, write, and ast_edit do not request ACP permission", async () => { const wrappedEdit = session.agent.state.tools.find(t => t.name === "edit"); const wrappedWrite = session.agent.state.tools.find(t => t.name === "write"); const wrappedAstEdit = session.agent.state.tools.find(t => t.name === "ast_edit"); - expect(wrappedEdit).toBeDefined(); - expect(wrappedWrite).toBeDefined(); - expect(wrappedAstEdit).toBeDefined(); await wrappedEdit!.execute("call-edit", { path: "/tmp/foo.ts" }, undefined, undefined as never, undefined as never); await wrappedWrite!.execute( @@ -383,12 +366,10 @@ it("edit delete and move operations request ACP permission before executing", as return { outcome: "selected", optionId: "allow_once", kind: "allow_once" }; }, }; - const permissionSpy = spyOn(bridge, "requestPermission"); session = await createSession([editTool], bridge); await session.setActiveToolsByName(["edit"]); const wrappedEdit = session.agent.state.tools.find(t => t.name === "edit"); - expect(wrappedEdit).toBeDefined(); await wrappedEdit!.execute( "call-edit-delete", @@ -405,7 +386,6 @@ it("edit delete and move operations request ACP permission before executing", as undefined as never, ); - expect(permissionSpy).toHaveBeenCalledTimes(2); expect(requests.map(({ title, locations }) => ({ title, locations }))).toEqual([ { title: "Delete /tmp/gone.ts", locations: [{ path: "/tmp/gone.ts" }] }, { title: "Move /tmp/old.ts to /tmp/new.ts", locations: [{ path: "/tmp/old.ts" }, { path: "/tmp/new.ts" }] }, @@ -427,7 +407,6 @@ it("edit delete operations take precedence over stale rename metadata", async () await session.setActiveToolsByName(["edit"]); const wrappedEdit = session.agent.state.tools.find(t => t.name === "edit"); - expect(wrappedEdit).toBeDefined(); await wrappedEdit!.execute( "call-edit-delete-with-rename", @@ -457,7 +436,6 @@ it("apply_patch delete operations take precedence over earlier moves", async () await session.setActiveToolsByName(["edit"]); const wrappedEdit = session.agent.state.tools.find(t => t.name === "edit"); - expect(wrappedEdit).toBeDefined(); await wrappedEdit!.execute( "call-apply-patch-delete-after-move", @@ -519,7 +497,6 @@ it("apply_patch custom-wire delete requests ACP permission through agent dispatc locations: [{ path: "/tmp/gone.ts" }], }, ]); - expect(requests).toHaveLength(1); }); it("patch-mode delete operations take precedence over earlier moves", async () => { @@ -536,7 +513,6 @@ it("patch-mode delete operations take precedence over earlier moves", async () = await session.setActiveToolsByName(["edit"]); const wrappedEdit = session.agent.state.tools.find(t => t.name === "edit"); - expect(wrappedEdit).toBeDefined(); await wrappedEdit!.execute( "call-patch-delete-after-move", @@ -569,7 +545,6 @@ it("always-allowing edit moves does not bypass patch-mode calls that also delete await session.setActiveToolsByName(["edit"]); const wrappedEdit = session.agent.state.tools.find(t => t.name === "edit"); - expect(wrappedEdit).toBeDefined(); await wrappedEdit!.execute( "call-edit-move", @@ -610,7 +585,6 @@ it("permission requests report the gated tool call as pending", async () => { await session.setActiveToolsByName(["bash"]); const wrappedBash = session.agent.state.tools.find(t => t.name === "bash"); - expect(wrappedBash).toBeDefined(); await wrappedBash!.execute("call-bash", { command: "echo hi" }, undefined, undefined as never, undefined as never); @@ -637,7 +611,6 @@ it("bash permission requests include execute metadata and command content", asyn await session.setActiveToolsByName(["bash"]); const wrappedBash = session.agent.state.tools.find(t => t.name === "bash"); - expect(wrappedBash).toBeDefined(); await wrappedBash!.execute( "call-bash-rich", @@ -668,7 +641,6 @@ it("ordinary edit calls still bypass ACP permission after rejecting edit moves f await session.setActiveToolsByName(["edit"]); const wrappedEdit = session.agent.state.tools.find(t => t.name === "edit"); - expect(wrappedEdit).toBeDefined(); await expect( wrappedEdit!.execute( @@ -699,7 +671,6 @@ it("edit create operations with rename metadata do not request ACP move permissi await session.setActiveToolsByName(["edit"]); const wrappedEdit = session.agent.state.tools.find(t => t.name === "edit"); - expect(wrappedEdit).toBeDefined(); await wrappedEdit!.execute( "call-edit-create", @@ -727,7 +698,6 @@ it("always-allowing edit moves does not bypass later edit delete permission", as await session.setActiveToolsByName(["edit"]); const wrappedEdit = session.agent.state.tools.find(t => t.name === "edit"); - expect(wrappedEdit).toBeDefined(); await wrappedEdit!.execute( "call-edit-move", @@ -756,7 +726,6 @@ it("setClientBridge wraps tools that were already active", async () => { session.setClientBridge(bridge); const wrappedBash = session.agent.state.tools.find(t => t.name === "bash"); - expect(wrappedBash).toBeDefined(); await wrappedBash!.execute("call-1", { command: "echo hi" }, undefined, undefined as never, undefined as never); @@ -774,7 +743,6 @@ it("aborting an open permission request rejects without executing the tool", asy session = await createSession([bashTool], bridge); await session.setActiveToolsByName(["bash"]); const wrappedBash = session.agent.state.tools.find(t => t.name === "bash"); - expect(wrappedBash).toBeDefined(); const abortController = new AbortController(); const execution = wrappedBash!.execute( @@ -802,7 +770,6 @@ it("reject_once: throws ToolError and never calls underlying execute", async () await session.setActiveToolsByName(["bash"]); const wrappedBash = session.agent.state.tools.find(t => t.name === "bash"); - expect(wrappedBash).toBeDefined(); await expect( wrappedBash!.execute("call-1", { command: "echo hi" }, undefined, undefined as never, undefined as never), @@ -818,7 +785,6 @@ it("unknown selected permission option ID fails closed without executing", async await session.setActiveToolsByName(["bash"]); const wrappedBash = session.agent.state.tools.find(t => t.name === "bash"); - expect(wrappedBash).toBeDefined(); await expect( wrappedBash!.execute("call-unknown", { command: "echo hi" }, undefined, undefined as never, undefined as never), @@ -838,7 +804,6 @@ it("allow_always: caches decision and calls bridge only once for subsequent exec await session.setActiveToolsByName(["bash"]); const wrappedBash = session.agent.state.tools.find(t => t.name === "bash"); - expect(wrappedBash).toBeDefined(); // First call — bridge is consulted, decision cached. await wrappedBash!.execute("call-1", { command: "echo a" }, undefined, undefined as never, undefined as never); @@ -913,7 +878,6 @@ it("read tool: requestPermission is never called for non-gated tools", async () await session.setActiveToolsByName(["read"]); const wrappedRead = session.agent.state.tools.find(t => t.name === "read"); - expect(wrappedRead).toBeDefined(); await wrappedRead!.execute("call-1", {}, undefined, undefined as never, undefined as never); diff --git a/packages/coding-agent/test/agent-session-auto-compaction-progress-guard.test.ts b/packages/coding-agent/test/agent-session-auto-compaction-progress-guard.test.ts index 7f91eaad5..7e36556f1 100644 --- a/packages/coding-agent/test/agent-session-auto-compaction-progress-guard.test.ts +++ b/packages/coding-agent/test/agent-session-auto-compaction-progress-guard.test.ts @@ -247,7 +247,6 @@ describe("AgentSession auto-compaction progress guard", () => { expect(promptSpy).not.toHaveBeenCalled(); expect(continueSpy).not.toHaveBeenCalled(); expect(todoReminders.length).toBe(0); - expect(session.isStreaming).toBe(false); const noProgress = notices.filter(n => n.source === NOTICE_SOURCE && n.message.includes(NO_PROGRESS_FRAGMENT)); expect(noProgress.length).toBe(1); @@ -334,7 +333,6 @@ describe("AgentSession auto-compaction progress guard", () => { expect(promptSpy).not.toHaveBeenCalled(); expect(continueSpy).toHaveBeenCalledTimes(1); - expect(session.agent.hasQueuedMessages()).toBe(false); const noProgress = notices.filter(n => n.source === NOTICE_SOURCE && n.message.includes(NO_PROGRESS_FRAGMENT)); expect(noProgress.length).toBe(1); }); @@ -401,7 +399,6 @@ describe("AgentSession auto-compaction progress guard", () => { expect(promptSpy).not.toHaveBeenCalled(); expect(continueSpy).toHaveBeenCalledTimes(1); - expect(session.agent.hasQueuedMessages()).toBe(false); const noProgress = notices.filter(n => n.source === NOTICE_SOURCE && n.message.includes(NO_PROGRESS_FRAGMENT)); expect(noProgress.length).toBe(1); }); @@ -797,7 +794,6 @@ describe("AgentSession auto-compaction progress guard", () => { expect(promptSpy).not.toHaveBeenCalled(); expect(continueSpy).toHaveBeenCalledTimes(1); - expect(session.agent.hasQueuedMessages()).toBe(false); expect(sessionManager.getBranch()).toContainEqual( expect.objectContaining({ type: "message", @@ -1191,7 +1187,6 @@ describe("AgentSession auto-compaction progress guard", () => { expect(startCount()).toBe(1); expect(continueSpy).not.toHaveBeenCalled(); - expect(session.isStreaming).toBe(false); const noProgress = notices.filter(n => n.source === NOTICE_SOURCE && n.message.includes(NO_PROGRESS_FRAGMENT)); expect(noProgress.length).toBe(1); expect(noProgress[0].level).toBe("warning"); diff --git a/packages/coding-agent/test/agent-session-retry-fallback.test.ts b/packages/coding-agent/test/agent-session-retry-fallback.test.ts index 3696e2e37..5e037735c 100644 --- a/packages/coding-agent/test/agent-session-retry-fallback.test.ts +++ b/packages/coding-agent/test/agent-session-retry-fallback.test.ts @@ -19,11 +19,7 @@ import { parseModelPattern, parseModelString } from "@oh-my-pi/pi-coding-agent/c import { Settings } from "@oh-my-pi/pi-coding-agent/config/settings"; import { ExtensionRuntime, loadExtensionFromFactory } from "@oh-my-pi/pi-coding-agent/extensibility/extensions/loader"; import { ExtensionRunner } from "@oh-my-pi/pi-coding-agent/extensibility/extensions/runner"; -import { IrcBus } from "@oh-my-pi/pi-coding-agent/irc/bus"; -import { AgentHubOverlayComponent } from "@oh-my-pi/pi-coding-agent/modes/components/agent-hub"; -import { SessionObserverRegistry } from "@oh-my-pi/pi-coding-agent/modes/session-observer-registry"; import { initTheme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme"; -import { AgentRegistry } from "@oh-my-pi/pi-coding-agent/registry/agent-registry"; import { AgentSession, type AgentSessionEvent } from "@oh-my-pi/pi-coding-agent/session/agent-session"; import { AuthStorage } from "@oh-my-pi/pi-coding-agent/session/auth-storage"; import type { ServingModel } from "@oh-my-pi/pi-coding-agent/session/retry-fallback-chains"; @@ -239,28 +235,6 @@ describe("AgentSession retry fallback", () => { role: "default", }, ]); - const registry = new AgentRegistry(); - registry.register({ - id: "fallback-agent", - displayName: "Fallback Agent", - kind: "sub", - session, - }); - const hub = new AgentHubOverlayComponent({ - observers: new SessionObserverRegistry(), - hubKeys: [], - onDone: () => {}, - requestRender: () => {}, - registry, - irc: new IrcBus(registry), - }); - try { - expect(Bun.stripANSI(hub.render(120).join("\n"))).toContain( - `fallback → ${secondFallback.provider}/${secondFallback.id}`, - ); - } finally { - hub.dispose(); - } }); it("forwards retry fallback events to extension handlers", async () => { @@ -1445,7 +1419,7 @@ describe("AgentSession retry fallback", () => { } }); - expect(session.setAdvisorEnabled(true)).toBe(true); + session.setAdvisorEnabled(true); await session.prompt("Complete one primary turn"); await session.waitForIdle(); // The catch-up gate releases immediately while the advisor is mid-failure @@ -1534,7 +1508,7 @@ describe("AgentSession retry fallback", () => { advisorTools: [], advisorStreamFn: advisorMock.stream, }); - expect(session.setAdvisorEnabled(true)).toBe(true); + session.setAdvisorEnabled(true); const credentialStarted = Promise.withResolvers(); const releaseCredential = Promise.withResolvers(); diff --git a/packages/coding-agent/test/autoresearch-tools.test.ts b/packages/coding-agent/test/autoresearch-tools.test.ts index 0f9eb0f2c..e2c6ba833 100644 --- a/packages/coding-agent/test/autoresearch-tools.test.ts +++ b/packages/coding-agent/test/autoresearch-tools.test.ts @@ -212,7 +212,6 @@ describe("init_experiment", () => { const storage = await openAutoresearchStorage(dir); const session = storage.getActiveSession(); - expect(session).not.toBeNull(); expect(session?.primaryMetric).toBe("runtime_ms"); expect(session?.scopePaths).toEqual(["src", "src/foo"]); expect(session?.offLimits).toEqual(["test"]); @@ -521,10 +520,7 @@ describe("log_experiment", () => { createCtx(dir), ); const details = result.details as LogDetails; - expect(details.experiment.status).toBe("keep"); - expect(details.experiment.metric).toBe(10); expect(details.state.bestMetric).toBe(10); - expect(details.state.results).toHaveLength(1); expect(runtime.state.bestMetric).toBe(10); }); @@ -869,8 +865,7 @@ describe("update_notes", () => { getRuntime: () => runtime, pi: harness.api, }); - const result = await notes.execute("n", { body: "## Plan\n- step one\n" }, undefined, undefined, createCtx(dir)); - expect(result.details?.notes).toContain("step one"); + await notes.execute("n", { body: "## Plan\n- step one\n" }, undefined, undefined, createCtx(dir)); expect(runtime.state.notes).toContain("step one"); const append = await notes.execute( diff --git a/packages/coding-agent/test/bash-executor.test.ts b/packages/coding-agent/test/bash-executor.test.ts index c3e61c4bb..c06b6e3a8 100644 --- a/packages/coding-agent/test/bash-executor.test.ts +++ b/packages/coding-agent/test/bash-executor.test.ts @@ -112,27 +112,6 @@ describe("executeBash", () => { expect(buildMinimizerOptions(group)).toBeUndefined(); }); - it("forwards source outline and legacy filter settings to native minimizer options", () => { - const group: ShellMinimizerSettings = { - enabled: true, - settingsPath: "minimizer.toml", - only: ["git"], - except: ["docker"], - maxCaptureBytes: 1234, - sourceOutlineLevel: "aggressive", - legacyFilters: true, - }; - expect(buildMinimizerOptions(group)).toEqual({ - enabled: true, - settingsPath: "minimizer.toml", - only: ["git"], - except: ["docker"], - maxCaptureBytes: 1234, - sourceOutlineLevel: "aggressive", - legacyFilters: true, - }); - }); - it.each([ ["cd", true], [" cd child ", true], @@ -753,7 +732,6 @@ exit 64 expect(result.cancelled).toBe(true); expect(result.output).toContain("streamed-before-timeout"); expect(result.output).toContain("Command timed out after 1 seconds"); - expect(nativeSignal).toBeDefined(); expect(nativeSignal?.aborted).toBe(false); expect(abortSpy).toHaveBeenCalledTimes(1); }); @@ -925,12 +903,10 @@ exit 64 cwd: tempDir, timeout: 5000, onChunk: chunk => { - expect(chunk.length).toBeGreaterThan(0); chunks.push(chunk); }, }); // At least one chunk should have been delivered to onChunk - expect(chunks.length).toBeGreaterThan(0); const combined = chunks.join(""); expect(combined).toContain("line1"); // Final result always has the complete output regardless of chunk throttle @@ -1062,7 +1038,6 @@ exit 64 PATH: Bun.env.PATH ?? "", HOME: tempDir, }); - expect(snapshotPath).not.toBeNull(); const snapshot = fs.readFileSync(snapshotPath!, "utf8"); expect(snapshot).toContain("pi_snapshot_large_function"); expect(snapshot).not.toContain("base64 -d"); @@ -1267,7 +1242,6 @@ exit 64 expect(result.cancelled).toBe(true); expect(result.output).toContain("flushed-during-timeout"); expect(result.output).toContain("Command timed out after 1 seconds"); - expect(nativeSignal).toBeDefined(); expect(nativeSignal?.aborted).toBe(false); expect(abortSpy).not.toHaveBeenCalled(); }); diff --git a/packages/coding-agent/test/collab/guest-ui-request.test.ts b/packages/coding-agent/test/collab/guest-ui-request.test.ts index 8c465c88b..f1a829628 100644 --- a/packages/coding-agent/test/collab/guest-ui-request.test.ts +++ b/packages/coding-agent/test/collab/guest-ui-request.test.ts @@ -546,7 +546,6 @@ describe("collab proto handshake (#4049)", () => { try { const welcome = await guest.nextFrame(); if (welcome.t !== "welcome") throw new Error(`expected welcome, got ${welcome.t}`); - expect(welcome.proto).toBe(COLLAB_PROTO); expect(welcome.proto).toBe(3); const pending = host.requestGuestUi({ kind: "select", title: "Continue?", options: ["Yes"] }); @@ -837,9 +836,6 @@ describe("guest ask multi-select Next gating (#4375 PRRT_kwDOQxs0bc6OFbDW)", () const first = await nextUiRequest(guest); const firstLabels = selectLabels(first); expect(firstLabels).not.toContain("Next →"); - expect(firstLabels).toContain("Option A"); - expect(firstLabels).toContain("Other (type your own)"); - expect(firstLabels).toContain("Chat about this"); // Guest toggles Option A — a real answer, not Next/Other/Chat. guest.socket.send({ t: "ui-response", reqId: first.request.reqId, value: "Option A" }); @@ -848,7 +844,6 @@ describe("guest ask multi-select Next gating (#4375 PRRT_kwDOQxs0bc6OFbDW)", () const second = await nextUiRequest(guest); const secondLabels = selectLabels(second); expect(secondLabels).toContain("Next →"); - expect(secondLabels).toContain("Option A"); // Guest selects Next to submit. guest.socket.send({ t: "ui-response", reqId: second.request.reqId, value: "Next →" }); diff --git a/packages/coding-agent/test/compaction.test.ts b/packages/coding-agent/test/compaction.test.ts index e0cc2133b..960ab78c0 100644 --- a/packages/coding-agent/test/compaction.test.ts +++ b/packages/coding-agent/test/compaction.test.ts @@ -213,7 +213,6 @@ describe("getLastAssistantUsage", () => { ]; const usage = getLastAssistantUsage(entries); - expect(usage).not.toBeNull(); expect(usage!.input).toBe(200); }); @@ -231,7 +230,6 @@ describe("getLastAssistantUsage", () => { ]; const usage = getLastAssistantUsage(entries); - expect(usage).not.toBeNull(); expect(usage!.input).toBe(100); }); @@ -529,7 +527,6 @@ describe("remote compaction setting", () => { remoteEnabled: false, remoteEndpoint: "https://compaction.example.test/summarize", }); - expect(preparation).toBeDefined(); if (!preparation) { throw new Error("Expected compaction preparation"); } @@ -607,7 +604,6 @@ describe("remote compaction setting", () => { keepRecentTokens: 1000, remoteEnabled: true, }); - expect(preparation).toBeDefined(); if (!preparation) { throw new Error("Expected compaction preparation"); } @@ -1409,7 +1405,6 @@ describe.skipIf(!e2eApiKey("ANTHROPIC_API_KEY"))("LLM summarization", () => { const model = getBundledModel("anthropic", "claude-sonnet-4-5")!; const preparation = prepareCompaction(entries, DEFAULT_COMPACTION_SETTINGS); - expect(preparation).toBeDefined(); const compactionResult = await compact(preparation!, model, e2eApiKey("ANTHROPIC_API_KEY")!); diff --git a/packages/coding-agent/test/core/apply-patch.test.ts b/packages/coding-agent/test/core/apply-patch.test.ts index 489b08636..1db1fe7e8 100644 --- a/packages/coding-agent/test/core/apply-patch.test.ts +++ b/packages/coding-agent/test/core/apply-patch.test.ts @@ -314,9 +314,8 @@ describe("applyPatch", () => { }); test("create file", async () => { - const result = await applyPatch({ path: "add.txt", op: "create", diff: "ab\ncd" }, { cwd: tempDir }); + await applyPatch({ path: "add.txt", op: "create", diff: "ab\ncd" }, { cwd: tempDir }); - expect(result.change.type).toBe("create"); expect(await Bun.file(path.join(tempDir, "add.txt")).text()).toBe("ab\ncd\n"); }); @@ -324,12 +323,11 @@ describe("applyPatch", () => { const target = path.join(tempDir, "exists.txt"); await Bun.write(target, "original\n"); - const result = await applyPatch( + await applyPatch( { path: "exists.txt", op: "create", diff: "replacement\n" }, { cwd: tempDir, allowCreateOverwrite: true }, ); - expect(result.change.type).toBe("create"); expect(await Bun.file(target).text()).toBe("replacement\n"); }); @@ -337,9 +335,8 @@ describe("applyPatch", () => { const filePath = path.join(tempDir, "del.txt"); await Bun.write(filePath, "x"); - const result = await applyPatch({ path: "del.txt", op: "delete" }, { cwd: tempDir }); + await applyPatch({ path: "del.txt", op: "delete" }, { cwd: tempDir }); - expect(result.change.type).toBe("delete"); expect(fs.existsSync(filePath)).toBe(false); }); @@ -347,12 +344,8 @@ describe("applyPatch", () => { const filePath = path.join(tempDir, "update.txt"); await Bun.write(filePath, "foo\nbar\n"); - const result = await applyPatch( - { path: "update.txt", op: "update", diff: "@@\n foo\n-bar\n+baz" }, - { cwd: tempDir }, - ); + await applyPatch({ path: "update.txt", op: "update", diff: "@@\n foo\n-bar\n+baz" }, { cwd: tempDir }); - expect(result.change.type).toBe("update"); expect(await Bun.file(filePath).text()).toBe("foo\nbaz\n"); }); @@ -365,7 +358,6 @@ describe("applyPatch", () => { { cwd: tempDir }, ); - expect(result.change.type).toBe("update"); expect(result.change.newPath).toBe(path.join(tempDir, "dst.txt")); expect(fs.existsSync(srcPath)).toBe(false); expect(await Bun.file(path.join(tempDir, "dst.txt")).text()).toBe("line2\n"); diff --git a/packages/coding-agent/test/discovery/claude-plugins.test.ts b/packages/coding-agent/test/discovery/claude-plugins.test.ts index cd5108efb..d38c62c0f 100644 --- a/packages/coding-agent/test/discovery/claude-plugins.test.ts +++ b/packages/coding-agent/test/discovery/claude-plugins.test.ts @@ -35,7 +35,6 @@ describe("parseClaudePluginsRegistry", () => { }); const result = parseClaudePluginsRegistry(content); - expect(result).not.toBeNull(); expect(result?.version).toBe(2); expect(result?.plugins["my-plugin@marketplace"]).toHaveLength(1); }); @@ -414,10 +413,8 @@ describe("listClaudePluginRoots", () => { const result = await loadCapability("skills", { cwd: tempDir }); expect(result.warnings).toEqual([]); - expect(result.all.length).toBeGreaterThan(0); const found = result.all.find(skill => skill.name === "manifest-skill"); - expect(found).toBeDefined(); expect(found?.path).toContain(path.join(".claude", "skills", "manifest-skill", "SKILL.md")); }); test("keeps plugin skills out of slash commands while loading them as skills", async () => { @@ -504,7 +501,6 @@ describe("listClaudePluginRoots", () => { }); const server = result.all.find(item => item.name === "context7:context7"); - expect(server).toBeDefined(); expect(server?.url).toBe("https://mcp.context7.example/mcp"); expect(server?.headers).toEqual({ CONTEXT7_API_KEY: "ctx7sk-test-key" }); } finally { @@ -625,7 +621,6 @@ describe("listClaudePluginRoots", () => { expect(result.warnings).toEqual([]); const server = result.all.find(item => item.name === "inline-mcp:local"); - expect(server).toBeDefined(); expect(server?.command).toBe(path.join(pluginPath, "bin", "server")); expect(server?.args).toEqual(["run"]); }); @@ -800,10 +795,8 @@ describe("listClaudePluginRoots", () => { const result = await loadCapability("slash-commands", { cwd: tempDir }); expect(result.warnings).toEqual([]); - expect(result.all.length).toBeGreaterThan(0); const found = result.all.find(command => command.name === "manifest-commands:ship"); - expect(found).toBeDefined(); expect(found?.path).toContain(path.join(".claude", "commands", "ship.md")); }); @@ -840,7 +833,6 @@ describe("listClaudePluginRoots", () => { expect(result.warnings).toEqual([]); const found = result.all.find(command => command.name === "manifest-commands-key:plan"); - expect(found).toBeDefined(); expect(found?.path).toContain(path.join(".claude", "commands", "plan.md")); }); @@ -1368,7 +1360,6 @@ describe("discoverAgents plugin precedence", () => { const result = await discoverAgents(tempDir, tempDir); const found = result.agents.find(agent => agent.name === agentName); - expect(found).toBeDefined(); expect(found?.source).toBe("project"); expect(found?.filePath).toContain(projectPluginPath); }); diff --git a/packages/coding-agent/test/extensions-discovery.test.ts b/packages/coding-agent/test/extensions-discovery.test.ts index 518329463..d3a185b79 100644 --- a/packages/coding-agent/test/extensions-discovery.test.ts +++ b/packages/coding-agent/test/extensions-discovery.test.ts @@ -694,7 +694,6 @@ describe("extensions discovery", () => { const loadedHook = result.extensions.find(extension => extension.path === hookPath); expect(result.errors).toHaveLength(0); - expect(loadedHook).toBeDefined(); expect(loadedHook?.handlers.has("tool_call")).toBe(true); }); @@ -726,7 +725,6 @@ describe("extensions discovery", () => { expect(result.errors).toHaveLength(0); expect(result.extensions.find(extension => extension.path === extensionPath)).toBeUndefined(); - expect(loadedHook).toBeDefined(); expect(loadedHook?.handlers.has("tool_call")).toBe(true); }); diff --git a/packages/coding-agent/test/extensions-runner.test.ts b/packages/coding-agent/test/extensions-runner.test.ts index a15152e2f..059cf39c3 100644 --- a/packages/coding-agent/test/extensions-runner.test.ts +++ b/packages/coding-agent/test/extensions-runner.test.ts @@ -85,26 +85,6 @@ describe("ExtensionRunner", () => { }; }; - it("exposes caller localProtocolOptions through extension context", async () => { - const localProtocolOptions = { - getArtifactsDir: () => tempDir.join("artifacts"), - getSessionId: () => "runner-session", - }; - const result = await loadTestExtensions(); - const runner = new ExtensionRunner( - result.extensions, - result.runtime, - tempDir.path(), - sessionManager, - modelRegistry, - undefined, - undefined, - localProtocolOptions, - ); - - expect(runner.createContext().localProtocolOptions).toBe(localProtocolOptions); - }); - it("reflects SessionManager.moveTo() changes instead of the constructor-time snapshot (/move)", async () => { const dirA = tempDir.join("dirA"); const dirB = tempDir.join("dirB"); @@ -2417,38 +2397,6 @@ describe("ExtensionRunner", () => { expect(fs.existsSync(recordPath)).toBe(false); // tool never executed }); - it("executes with the original input when no handler returns a replacement", async () => { - const recordPath = path.join(tempDir.path(), "override-absent.jsonl"); - const extCode = ` - export default function(pi) { - pi.on("tool_call", async (event) => { - if (event.toolName !== "bash") return; - // observe only; no input override - }); - } - `; - fs.writeFileSync(path.join(extensionsDir, "tool-call-no-override.ts"), extCode); - - const result = await loadTestExtensions(); - const runner = new ExtensionRunner( - result.extensions, - result.runtime, - tempDir.path(), - sessionManager, - modelRegistry, - ); - const wrapped = new ExtensionToolWrapper(createRecordingTool(recordPath), runner); - - await wrapped.execute("tool-call-id", { command: "echo original" }); - - const executed = fs - .readFileSync(recordPath, "utf8") - .trim() - .split("\n") - .map(line => JSON.parse(line)); - expect(executed).toEqual([{ command: "echo original" }]); - }); - // A tool whose approval policy depends on its args: the command "rm -rf" resolves to deny, // anything else is exec. Lets a test prove the post-override approval re-check (P1). function createArgGatedTool(recordPath: string): AgentTool { diff --git a/packages/coding-agent/test/hindsight-backend.test.ts b/packages/coding-agent/test/hindsight-backend.test.ts index 9a7c23e35..f22e74f50 100644 --- a/packages/coding-agent/test/hindsight-backend.test.ts +++ b/packages/coding-agent/test/hindsight-backend.test.ts @@ -134,7 +134,6 @@ describe("hindsightBackend.start", () => { taskDepth: 0, }); - expect(session.getHindsightSessionState()).toBeDefined(); (session as { sessionId: string | null }).sessionId = "s-after"; session.getHindsightSessionState()?.setSessionId("s-after"); expect(session.getHindsightSessionState()?.sessionId).toBe("s-after"); @@ -193,7 +192,6 @@ describe("hindsightBackend.start", () => { taskDepth: 0, }); const parentState = parentSession.getHindsightSessionState(); - expect(parentState).toBeDefined(); // Subagent runs with taskDepth > 0 should alias the parent. const subSession = makeFakeSession({ sessionId: "sub" }); @@ -206,7 +204,6 @@ describe("hindsightBackend.start", () => { parentHindsightSessionState: parentState, }); const subState = subSession.getHindsightSessionState(); - expect(subState).toBeDefined(); expect(subState?.aliasOf).toBe(parentState); expect(subState?.bankId).toBe(parentState?.bankId); expect(subState?.client).toBe(parentState?.client); @@ -272,7 +269,6 @@ describe("hindsightBackend.preCompactionContext", () => { const messages: AgentMessage[] = [{ role: "user", content: "What did we decide?", timestamp: 0 } as never]; const ctx = await hindsightBackend.preCompactionContext?.(messages, settings, session as never); - expect(ctx).toBeDefined(); expect(ctx).toContain(""); expect(ctx).toContain("remembered fact"); }); @@ -389,7 +385,6 @@ describe("hindsightBackend first-turn injection", () => { }); const state = session.getHindsightSessionState(); - expect(state).toBeDefined(); state!.lastRecallSnippet = "\nremembered fact\n"; const prompt = await hindsightBackend.buildDeveloperInstructions("/tmp", settings, session as never); @@ -416,12 +411,10 @@ describe("hindsightBackend first-turn injection", () => { taskDepth: 0, }); const state = session.getHindsightSessionState(); - expect(state).toBeDefined(); state!.mentalModelsSnippet = "\n# User Preferences\nprefers tabs\n"; state!.lastRecallSnippet = "\nrecalled fact\n"; const prompt = await hindsightBackend.buildDeveloperInstructions("/tmp", settings, session as never); - expect(prompt).toBeDefined(); // `` and `` are mentioned in STATIC_INSTRUCTIONS // bullets too. Match the actual injected block opener (tag + newline) // to disambiguate documentation prose from the injected payloads. @@ -456,7 +449,6 @@ describe("hindsightBackend first-turn injection", () => { // Wait for the kicked-off load to settle. await session.getHindsightSessionState()?.mentalModelsLoadPromise; const state = session.getHindsightSessionState(); - expect(state).toBeDefined(); expect(state!.mentalModelsSnippet).toBeUndefined(); expect(state!.mentalModelsLoadedAt).toBeDefined(); const initialLoadedAt = state!.mentalModelsLoadedAt!; @@ -479,7 +471,6 @@ describe("hindsightBackend first-turn injection", () => { const ok = await reloadMentalModelsForSession(session as never); expect(ok).toBe(true); - expect(state!.mentalModelsSnippet).toBeDefined(); expect(state!.mentalModelsSnippet).toContain("# User Preferences"); expect(state!.mentalModelsSnippet).toContain("prefers concise prose"); expect(state!.mentalModelsLoadedAt).toBeGreaterThan(initialLoadedAt - 1000); @@ -616,7 +607,6 @@ describe("hindsightBackend live bank routing", () => { await Bun.sleep(0); const next = session.getHindsightSessionState(); - expect(next).toBeDefined(); expect(next?.bankId).toBe("Minigames"); // Must be a brand-new state — the old one was disposed. expect(next).not.toBe(initial); @@ -649,7 +639,6 @@ describe("hindsightBackend live bank routing", () => { await Bun.sleep(0); const next = session.getHindsightSessionState(); - expect(next).toBeDefined(); expect(next?.bankId).toBe("omp-proj"); expect(next).not.toBe(initial); }); @@ -714,7 +703,6 @@ describe("hindsightBackend live bank routing", () => { await Bun.sleep(0); const next = session.getHindsightSessionState(); - expect(next).toBeDefined(); expect(next).not.toBe(initial); // With scoping=per-project the base falls back to the default ("omp"), // so the reset bank id picks up the project suffix from cwd. @@ -897,7 +885,6 @@ describe("hindsightBackend retain queue flush on session teardown", () => { taskDepth: 0, }); const state = session.getHindsightSessionState(); - expect(state).toBeDefined(); state!.enqueueRetain("durable fact", "test context"); diff --git a/packages/coding-agent/test/marketplace/manager.test.ts b/packages/coding-agent/test/marketplace/manager.test.ts index b0f672409..1097ee250 100644 --- a/packages/coding-agent/test/marketplace/manager.test.ts +++ b/packages/coding-agent/test/marketplace/manager.test.ts @@ -127,11 +127,7 @@ describe("MarketplaceManager", () => { // ── Marketplace lifecycle ────────────────────────────────────────────── it("addMarketplace with local fixture → appears in listMarketplaces", async () => { - const entry = await ctx.manager.addMarketplace(FIXTURE_DIR); - - expect(entry.name).toBe("test-marketplace"); - expect(entry.sourceType).toBe("local"); - expect(entry.sourceUri).toBe(FIXTURE_DIR); + await ctx.manager.addMarketplace(FIXTURE_DIR); const list = await ctx.manager.listMarketplaces(); expect(list).toHaveLength(1); @@ -167,7 +163,6 @@ describe("MarketplaceManager", () => { const added = await ctx.manager.addMarketplace(FIXTURE_DIR); const updated = await ctx.manager.updateMarketplace("test-marketplace"); - expect(updated.name).toBe("test-marketplace"); expect(updated.addedAt).toBe(added.addedAt); // updatedAt must be at or after addedAt expect(new Date(updated.updatedAt) >= new Date(added.addedAt)).toBe(true); @@ -201,7 +196,6 @@ describe("MarketplaceManager", () => { const instEntry = await ctx.manager.installPlugin("hello-plugin", "test-marketplace"); expect(instEntry.scope).toBe("user"); - expect(instEntry.version).toBe("1.0.0"); expect(fs.existsSync(instEntry.installPath)).toBe(true); const linkPath = path.join(ctx.tmpDir, "node_modules", "hello-plugin"); expect(fs.realpathSync(linkPath)).toBe(fs.realpathSync(instEntry.installPath)); @@ -560,7 +554,6 @@ describe("MarketplaceManager", () => { scope: "project", }); expect(instEntry.scope).toBe("project"); - expect(instEntry.version).toBe("1.0.0"); expect(fs.existsSync(instEntry.installPath)).toBe(true); // Persisted to the project registry with project scope — and absent from the user registry. diff --git a/packages/coding-agent/test/memory-tools.test.ts b/packages/coding-agent/test/memory-tools.test.ts index 5b882d92a..e3c68910c 100644 --- a/packages/coding-agent/test/memory-tools.test.ts +++ b/packages/coding-agent/test/memory-tools.test.ts @@ -788,11 +788,9 @@ describe("Mnemopi backend lifecycle", () => { const state = registerMnemopiState(config, { cwd: "/work/project-alpha", entries: () => entries }); const ownedDbPaths = getMnemopiScopedDbPaths(config); const sharedDbPath = ownedDbPaths.find(dbPath => dbPath === config.dbPath); - expect(sharedDbPath).toBeDefined(); const lock = new Database(sharedDbPath!); lock.exec("BEGIN IMMEDIATE"); const sharedMemory = state.globalMemory; - expect(sharedMemory).toBeDefined(); const sharedFlushCalled = Promise.withResolvers(); const sharedFlushSpy = vi.spyOn(sharedMemory!, "flushExtractions").mockImplementation(async () => { // Signal first: the exec below may throw SQLITE_BUSY while the lock is @@ -1397,7 +1395,6 @@ describe("memory_edit.execute (Mnemopi backend)", () => { items: [{ content }], }); const id = (await registeredMnemopiState?.recallResultsScoped(query))?.[0]?.id; - expect(id).toBeString(); return id!; } diff --git a/packages/coding-agent/test/model-discovery.test.ts b/packages/coding-agent/test/model-discovery.test.ts index 1c00d67b9..c25d30010 100644 --- a/packages/coding-agent/test/model-discovery.test.ts +++ b/packages/coding-agent/test/model-discovery.test.ts @@ -494,7 +494,6 @@ describe("ModelRegistry runtime discovery", () => { const zenmuxModels = getModelsForProvider(registry1, "zenmux"); const fable = zenmuxModels.find(m => m.id === "anthropic/claude-fable-5-free"); - expect(fable).toBeDefined(); expect(fable?.api).toBe("anthropic-messages"); expect(fable?.baseUrl).toBe("https://zenmux.ai/api/anthropic"); @@ -515,7 +514,6 @@ describe("ModelRegistry runtime discovery", () => { const offlineZenmuxModels = getModelsForProvider(registry2, "zenmux"); const offlineFable = offlineZenmuxModels.find(m => m.id === "anthropic/claude-fable-5-free"); - expect(offlineFable).toBeDefined(); expect(offlineFable?.api).toBe("anthropic-messages"); expect(offlineFable?.baseUrl).toBe("https://zenmux.ai/api/anthropic"); } finally { @@ -1039,7 +1037,6 @@ describe("ModelRegistry runtime discovery", () => { expect(llamaModels.some(m => m.id === "llama-3.2:3b")).toBe(true); const apiKey = await registry.getApiKey(llamaModels[0]); expect(apiKey).toBe("test-llama-key"); - expect(apiKey).not.toBe(kNoAuth); }); test("llama.cpp discovery without API key is treated as keyless", async () => { const fetchMock: FetchImpl = async (input, init) => { @@ -2315,7 +2312,6 @@ providers: const registry = new ModelRegistry(authStorage, modelsJsonPath, { fetch: fetchMock }); await registry.refresh(); const model = registry.find("proxy-test", "act_two"); - expect(model).toBeDefined(); expect(model?.name).toBe("Act Two"); }); @@ -2348,7 +2344,6 @@ providers: const registry = new ModelRegistry(authStorage, modelsJsonPath, { fetch: fetchMock }); await registry.refresh(); const model = registry.find("proxy-test", "gpt-5"); - expect(model).toBeDefined(); expect(model?.name).toBe("GPT-5"); }); @@ -2575,7 +2570,6 @@ providers: const registry = new ModelRegistry(authStorage, modelsJsonPath); const restored = registry.find("github-copilot", "gpt-5.6-sol-1m"); - expect(restored).toBeDefined(); expect(restored?.headers).toEqual(bundledBase.headers); }); diff --git a/packages/coding-agent/test/model-registry-runtime-provider.test.ts b/packages/coding-agent/test/model-registry-runtime-provider.test.ts index f7280e48c..6711d7284 100644 --- a/packages/coding-agent/test/model-registry-runtime-provider.test.ts +++ b/packages/coding-agent/test/model-registry-runtime-provider.test.ts @@ -109,7 +109,6 @@ describe("ModelRegistry runtime provider registration", () => { headerValue: string | undefined, ): Promise { const model = registry.find(providerName, modelId); - expect(model).toBeDefined(); expect(model?.baseUrl).toBe(baseUrl); expect(model?.headers?.[headerName]).toBe(headerValue); await registry.refresh("offline"); @@ -433,7 +432,6 @@ describe("ModelRegistry runtime provider registration", () => { await registry.refresh("offline"); const model = registry.find("runtime-provider", "runtime-model"); - expect(model).toBeDefined(); expect(model?.baseUrl).toBe("https://runtime.example.com/v1"); expect(model?.api).toBe("openai-completions"); }); @@ -456,7 +454,6 @@ describe("ModelRegistry runtime provider registration", () => { await registry.refresh("online"); const model = registry.find("runtime-provider", "online-survivor"); - expect(model).toBeDefined(); expect(model?.api).toBe("openai-completions"); }); @@ -950,7 +947,6 @@ describe("ModelRegistry runtime provider registration", () => { test("provider-scoped lookups preserve whole-catalog modifyModels projections", async () => { const hiddenModel = registry.getAll().find(model => model.provider === "anthropic"); - expect(hiddenModel).toBeDefined(); await authStorage.set("filtering-provider", { type: "oauth", access: "access-token", @@ -989,7 +985,6 @@ describe("ModelRegistry runtime provider registration", () => { test("provider-scoped lookups do not intern other providers' transient projections", async () => { const anthropicId = registry.getAll().find(model => model.provider === "anthropic")?.id; - expect(anthropicId).toBeDefined(); await authStorage.set("changing-provider", { type: "oauth", access: "access-token", @@ -1103,7 +1098,6 @@ describe("ModelRegistry runtime provider registration", () => { test("online discovery reapplies modifiers to an unprojected full catalog", async () => { const target = registry.getAll().find(model => model.provider === "anthropic"); - expect(target).toBeDefined(); await authStorage.set("renaming-provider", { type: "oauth", access: "access-token", @@ -1160,7 +1154,6 @@ describe("ModelRegistry runtime provider registration", () => { try { const targetBefore = registry.getAll()[0]; - expect(targetBefore).toBeDefined(); const targetSnapshot = structuredClone(targetBefore!); const anthropicBefore = registry.getAll().filter(model => model.provider === "anthropic").length; expect(anthropicBefore).toBeGreaterThan(0); diff --git a/packages/coding-agent/test/model-registry.test.ts b/packages/coding-agent/test/model-registry.test.ts index 088cf3d19..cb31133a1 100644 --- a/packages/coding-agent/test/model-registry.test.ts +++ b/packages/coding-agent/test/model-registry.test.ts @@ -342,13 +342,6 @@ describe("ModelRegistry", () => { } }); - test("rerouted bundled OpenAI models recompute inferred computer capability", () => { - const model = openaiProxy.find("openai", "gpt-5.4"); - - expect(model?.baseUrl).toBe("https://openai-proxy.example.com/v1"); - expect(model?.supportsComputerUse).toBe(false); - }); - test("overriding headers merges with model headers", () => { const anthropicModels = getModelsForProvider(anthropicProxyHeaders, "anthropic"); for (const model of anthropicModels) { @@ -364,6 +357,13 @@ describe("ModelRegistry", () => { } }); + test("rerouted bundled OpenAI models recompute inferred computer capability", () => { + const model = openaiProxy.find("openai", "gpt-5.4"); + + expect(model?.baseUrl).toBe("https://openai-proxy.example.com/v1"); + expect(model?.supportsComputerUse).toBe(false); + }); + test("provider header lookup excludes unrelated model overrides", () => { expect(xaiModelScopedHeaders.find("xai", otherXaiModelId)?.headers?.["X-Model-Tenant"]).toBe( "other-model-tenant", @@ -551,9 +551,9 @@ describe("ModelRegistry", () => { describe("provider compat overrides", () => { let providerCompat: ModelRegistry; let customCompat: ModelRegistry; + let customAnthropicCompat: ModelRegistry; let customModelCompat: ModelRegistry; let customResponsesCompat: ModelRegistry; - let customAnthropicCompat: ModelRegistry; beforeAll(() => { providerCompat = readonlyRegistry({ providers: { @@ -692,6 +692,22 @@ describe("ModelRegistry", () => { } }); + test("provider-level compat applies to custom models", () => { + const model = customCompat.find("demo", "demo-model"); + const compat = getOpenAICompat(model); + expect(compat?.supportsUsageInStreaming).toBe(false); + expect(compat?.maxTokensField).toBe("max_tokens"); + expect(compat?.cacheControlFormat).toBe("anthropic"); + }); + + test("custom Anthropic providers can opt into eager tool input streaming", () => { + const model = customAnthropicCompat.find("anthropic-proxy", "claude-haiku-4.5"); + expect(model?.compat).toMatchObject({ + supportsEagerToolInputStreaming: true, + allowAnthropicHeaderOverrides: true, + }); + }); + test("provider-level Anthropic compat survives dynamic discovery refresh", async () => { writeRawModelsJson({ anthropic: { @@ -718,22 +734,6 @@ describe("ModelRegistry", () => { expect(getReplayUnsignedThinking(registry.find("anthropic", "claude-sonnet-5"))).toBe(false); }); - test("provider-level compat applies to custom models", () => { - const model = customCompat.find("demo", "demo-model"); - const compat = getOpenAICompat(model); - expect(compat?.supportsUsageInStreaming).toBe(false); - expect(compat?.maxTokensField).toBe("max_tokens"); - expect(compat?.cacheControlFormat).toBe("anthropic"); - }); - - test("custom Anthropic providers can opt into eager tool input streaming", () => { - const model = customAnthropicCompat.find("anthropic-proxy", "claude-haiku-4.5"); - expect(model?.compat).toMatchObject({ - supportsEagerToolInputStreaming: true, - allowAnthropicHeaderOverrides: true, - }); - }); - test("custom Responses providers can disable original image detail", () => { const model = customResponsesCompat.find("cc-switch", "gpt-5.5"); const compat = getOpenAICompat(model); diff --git a/packages/coding-agent/test/oauth-flow.test.ts b/packages/coding-agent/test/oauth-flow.test.ts index 23225bbf9..3ed62624e 100644 --- a/packages/coding-agent/test/oauth-flow.test.ts +++ b/packages/coding-agent/test/oauth-flow.test.ts @@ -78,7 +78,6 @@ describe("mcp oauth flow", () => { const { url } = await flow.generateAuthUrl("test-state", "http://127.0.0.1:53172/callback"); const authUrl = new URL(url); - expect(registrationPayload).not.toBeNull(); expect((registrationPayload as { client_name?: string } | null)?.client_name).toBe("oh-my-pi"); expect((registrationPayload as { scope?: string } | null)?.scope).toBeUndefined(); expect(authUrl.searchParams.get("client_id")).toBe("registered-client-id"); @@ -105,7 +104,6 @@ describe("mcp oauth flow", () => { const { url } = await flow.generateAuthUrl("test-state", "http://127.0.0.1:53173/callback"); const authUrl = new URL(url); - expect(registrationPayload).not.toBeNull(); expect((registrationPayload as { scope?: string } | null)?.scope).toBe(scopes); expect(authUrl.searchParams.get("scope")).toBe(scopes); expect(authUrl.searchParams.get("client_id")).toBe("registered-client-id"); @@ -667,9 +665,6 @@ describe("mcp oauth flow", () => { {}, ); - expect(flow.resolvedClientId).toBeUndefined(); - expect(flow.registeredClientSecret).toBeUndefined(); - await flow.generateAuthUrl("test-state", "http://127.0.0.1:53173/callback"); expect(flow.resolvedClientId).toBe("registered-client-id"); @@ -1220,17 +1215,4 @@ describe("mcp oauth flow", () => { expect(tokenParams.get("resource")).toBe("https://token.example.com"); }); }); - - it("exposes authorizationUrl via a getter so callers can persist it on the credential", () => { - const flow = new MCPOAuthFlow( - { - authorizationUrl: "https://auth.example.com/authorize", - tokenUrl: "https://token.example.com/token", - clientId: "client-id", - }, - {}, - ); - - expect(flow.authorizationUrl).toBe("https://auth.example.com/authorize"); - }); }); diff --git a/packages/coding-agent/test/sdk-tool-activation.test.ts b/packages/coding-agent/test/sdk-tool-activation.test.ts index 1de587789..1d98ecd0e 100644 --- a/packages/coding-agent/test/sdk-tool-activation.test.ts +++ b/packages/coding-agent/test/sdk-tool-activation.test.ts @@ -1116,7 +1116,6 @@ describe("createAgentSession defaultInactive tool activation", () => { const mountedBefore = session.getMountedXdevToolNames(); const promptBefore = session.systemPrompt; const originalTool = session.getToolByName("bash"); - expect(originalTool).toBeDefined(); expect(session.hasBuiltInTool("bash")).toBe(true); const runner = session.extensionRunner; if (!runner) throw new Error("expected extension runner"); @@ -1931,7 +1930,6 @@ describe("createAgentSession defaultInactive tool activation", () => { try { expect(session.getAllToolNames()).toEqual(["read", "sdk_custom_tool"]); expect(session.getActiveToolNames()).toEqual(["read", "sdk_custom_tool"]); - expect(session.getToolByName("sdk_custom_tool")).toBeDefined(); } finally { await session.dispose(); } diff --git a/packages/coding-agent/test/session-manager-atomic-rewrite-race.test.ts b/packages/coding-agent/test/session-manager-atomic-rewrite-race.test.ts index 6a4d5729b..dad7ccdf5 100644 --- a/packages/coding-agent/test/session-manager-atomic-rewrite-race.test.ts +++ b/packages/coding-agent/test/session-manager-atomic-rewrite-race.test.ts @@ -303,7 +303,7 @@ describe("SessionManager atomic rewrite race", () => { // Simulate a Ctrl+C teardown: append a session_exit custom entry (fenced // because the atomic rewrite is active) and flushSync it. sessionManager.appendCustomEntry("session_exit", { reason: "sigterm", kind: "signal" }); - expect(() => sessionManager.flushSync()).not.toThrow(); + sessionManager.flushSync(); const sessionFile = sessionManager.getSessionFile(); if (!sessionFile) throw new Error("Expected session file"); @@ -528,7 +528,7 @@ describe("SessionManager fence relaxes when flushSync supersedes the atomic rewr // (2) flushSync supersedes the pending atomic (bumps #diskEpoch) and // publishes a synchronous body containing X1. - expect(() => sessionManager.flushSync()).not.toThrow(); + sessionManager.flushSync(); // (3) Post-flushSync append MUST take the hot path: pre-fix, the fence // stayed active and this entry was only marked dirty, then dropped when @@ -672,7 +672,7 @@ describe("SessionManager fence handoff across superseded rewrites", () => { // A fenced append flips fileIsCurrent so flushSync actually publishes, // bumping the epoch to 1 with the fenced entry captured in the body. sessionManager.appendCustomEntry("during_stale", { data: "X1" }); - expect(() => sessionManager.flushSync()).not.toThrow(); + sessionManager.flushSync(); // Newer rewrite scheduled at epoch=1. Parks at pauses[1]. Fence epoch = 1. const newer = sessionManager.rewriteEntries(); diff --git a/packages/coding-agent/test/settings-manager.test.ts b/packages/coding-agent/test/settings-manager.test.ts index 2e15e69c8..ca4833b62 100644 --- a/packages/coding-agent/test/settings-manager.test.ts +++ b/packages/coding-agent/test/settings-manager.test.ts @@ -7,8 +7,6 @@ import { createMockModel, registerMockApi } from "@oh-my-pi/pi-ai/providers/mock import { __providerInFlightForTesting, streamSimple } from "@oh-my-pi/pi-ai/stream"; import type { Context } from "@oh-my-pi/pi-ai/types"; import { - getDefault, - getEnumValues, onAppendOnlyModeChanged, onStatusLineSessionAccentChanged, resetSettingsForTest, @@ -391,56 +389,6 @@ describe("Settings", () => { }); }); - describe("defaults", () => { - it("keeps eight inline images live by default", async () => { - const settings = await Settings.init({ cwd: projectDir, agentDir }); - expect(settings.get("tui.maxInlineImages")).toBe(8); - }); - - it("keeps native terminal progress disabled by default", async () => { - const settings = await Settings.init({ cwd: projectDir, agentDir }); - expect(settings.get("terminal.showProgress")).toBe(false); - expect(getDefault("terminal.showProgress")).toBe(false); - }); - - it("shows tool activity by default", async () => { - const settings = await Settings.init({ cwd: projectDir, agentDir }); - expect(settings.get("display.hideToolActivity")).toBe(false); - expect(getDefault("display.hideToolActivity")).toBe(false); - }); - - it("keeps the normal startup splash disabled by default", async () => { - const settings = await Settings.init({ cwd: projectDir, agentDir }); - expect(settings.get("startup.showSplash")).toBe(false); - expect(getDefault("startup.showSplash")).toBe(false); - }); - - it("defaults provider in-flight request limits to an empty map", async () => { - const settings = Settings.isolated(); - expect(settings.get("providers.maxInFlightRequests")).toEqual({}); - expect(getDefault("providers.maxInFlightRequests")).toEqual({}); - }); - - it("exposes all tool calling mode options", () => { - const values = getEnumValues("tools.format"); - expect(values).toEqual([ - "auto", - "native", - "glm", - "hermes", - "kimi", - "xml", - "anthropic", - "deepseek", - "harmony", - "qwen3", - "gemini", - "gemma", - "minimax", - ]); - }); - }); - describe("get()", () => { it("resolves overrides, schema defaults, and falsey values", () => { const isolated = Settings.isolated({ @@ -454,7 +402,6 @@ describe("Settings", () => { expect(isolated.get("setupVersion")).toBe(0); expect(isolated.get("shellPath")).toBe(""); expect(isolated.get("enabledModels")).toEqual([]); - expect(isolated.get("tui.maxInlineImages")).toBe(getDefault("tui.maxInlineImages")); }); it("invalidates cached resolved values after set, override, and clearOverride", () => { @@ -559,7 +506,7 @@ describe("Settings", () => { }); try { - expect(() => isolated.set("provider.appendOnlyContext", "on")).not.toThrow(); + isolated.set("provider.appendOnlyContext", "on"); expect(received).toEqual(["on"]); } finally { unsubscribeThrower(); diff --git a/packages/coding-agent/test/tools.test.ts b/packages/coding-agent/test/tools.test.ts index 1c44b1071..260f23fac 100644 --- a/packages/coding-agent/test/tools.test.ts +++ b/packages/coding-agent/test/tools.test.ts @@ -847,8 +847,6 @@ describe("Coding Agent Tools", () => { const result = await readTool.execute("test-call-9", { path: testFile }); - expect(result.details).toBeDefined(); - expect(result.details?.truncation).toBeDefined(); expect(result.details?.truncation?.truncated).toBe(true); expect(result.details?.truncation?.truncatedBy).toBe("lines"); expect(result.details?.truncation?.totalLines).toBe(3500); @@ -1526,10 +1524,7 @@ describe("Coding Agent Tools", () => { const imageBlock = result.content.find( (c): c is { type: "image"; mimeType: string; data: string } => c.type === "image", ); - expect(imageBlock).toBeDefined(); expect(imageBlock?.mimeType).toBe("image/png"); - expect(typeof imageBlock?.data).toBe("string"); - expect((imageBlock?.data ?? "").length).toBeGreaterThan(0); }); it("returns metadata guidance (no image blocks) when inspect_image is enabled", async () => { @@ -1744,10 +1739,6 @@ describe("Coding Agent Tools", () => { }); const details = result.details as { diff?: string } | undefined; - expect(getTextOutput(result)).toContain("Successfully replaced"); - expect(details).toBeDefined(); - expect(details?.diff).toBeDefined(); - expect(typeof details?.diff).toBe("string"); expect(details?.diff).toContain("testing"); }); diff --git a/packages/coding-agent/test/tools/ask.test.ts b/packages/coding-agent/test/tools/ask.test.ts index 6a5688d26..740f3afee 100644 --- a/packages/coding-agent/test/tools/ask.test.ts +++ b/packages/coding-agent/test/tools/ask.test.ts @@ -463,7 +463,6 @@ describe("AskTool option descriptions", () => { it("renders descriptions under labels in ask call previews", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const rendered = askToolRenderer.renderCall( { question: "How should authentication continue?", @@ -941,7 +940,6 @@ describe("AskTool custom input", () => { expect(result.content[0].text).toContain("custom detail"); const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const rendered = askToolRenderer.renderResult(result, { expanded: true, isPartial: false }, theme!); const renderedText = stripAnsi(rendered.render(120).join("\n")); expect(renderedText).toContain("alpha"); @@ -1029,7 +1027,6 @@ describe("AskTool multiline custom input rendering", () => { expect(result.details?.customInput).toBe(multilineText); const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const rendered = askToolRenderer.renderResult(result, { expanded: true, isPartial: false }, theme!); const renderedText = stripAnsi(rendered.render(120).join("\n")); @@ -1084,7 +1081,6 @@ describe("AskTool multiline custom input rendering", () => { ); const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const rendered = askToolRenderer.renderResult(result, { expanded: true, isPartial: false }, theme!); const renderedText = stripAnsi(rendered.render(120).join("\n")); @@ -1339,7 +1335,6 @@ describe("AskTool multi-question navigation", () => { describe("AskTool option markers", () => { it("renders single-choice call options with circular radio markers, not checkboxes", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const rendered = askToolRenderer.renderCall( { question: "Pick one", options: [{ label: "Alpha" }, { label: "Beta" }] }, { expanded: true, isPartial: false }, @@ -1352,7 +1347,6 @@ describe("AskTool option markers", () => { it("renders multi-select call options with rectangular checkbox markers, not radios", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const rendered = askToolRenderer.renderCall( { question: "Pick many", options: [{ label: "Alpha" }, { label: "Beta" }], multi: true }, { expanded: true, isPartial: false }, @@ -1365,7 +1359,6 @@ describe("AskTool option markers", () => { it("keeps option rows stable across repeated renders", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const options = [ { label: "TypeScript" }, { label: "Rust" }, @@ -1417,7 +1410,6 @@ describe("AskTool option markers", () => { it("keeps single-question option rows stable across repeated renders", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); // The question body comes from the Markdown render cache, which returns // the SAME array on every render of identical text at identical width. // Appending option rows in place would poison that cached entry, so a @@ -1452,7 +1444,6 @@ describe("AskTool option markers", () => { }); it("renders single-choice result selection with a filled radio marker", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const rendered = askToolRenderer.renderResult( { content: [{ type: "text", text: "" }], @@ -1468,7 +1459,6 @@ describe("AskTool option markers", () => { it("renders multi-select result selections with checkbox markers", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const rendered = askToolRenderer.renderResult( { content: [{ type: "text", text: "" }], @@ -1486,7 +1476,6 @@ describe("AskTool option markers", () => { describe("askToolRenderer malformed call args", () => { it("renders double-encoded questions string instead of crashing the TUI", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); // Models occasionally JSON-encode the questions array as a string; a bare // string passes a truthy `.length` check but has no `.map` (TUI crash). const doubleEncoded = JSON.stringify([ @@ -1505,7 +1494,6 @@ describe("askToolRenderer malformed call args", () => { it("falls back to the error frame for unparseable questions without throwing", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); for (const questions of ["[{trunc", 42, { 0: { id: "x" } }]) { const rendered = askToolRenderer.renderCall( { questions } as never, @@ -1519,7 +1507,6 @@ describe("askToolRenderer malformed call args", () => { it("drops malformed question entries and option items while keeping valid ones", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const rendered = askToolRenderer.renderCall( { questions: [ diff --git a/packages/coding-agent/test/tools/grep-path-lists.test.ts b/packages/coding-agent/test/tools/grep-path-lists.test.ts index adbe10449..fb84ad3be 100644 --- a/packages/coding-agent/test/tools/grep-path-lists.test.ts +++ b/packages/coding-agent/test/tools/grep-path-lists.test.ts @@ -19,7 +19,7 @@ import { AgentRegistry } from "@oh-my-pi/pi-coding-agent/registry/agent-registry import type { SessionEntry, SessionTreeNode } from "@oh-my-pi/pi-coding-agent/session/session-entries"; import { ToolChoiceQueue } from "@oh-my-pi/pi-coding-agent/session/tool-choice-queue"; import { createTools, type ToolSession } from "@oh-my-pi/pi-coding-agent/tools"; -import { Text } from "@oh-my-pi/pi-tui"; +import type { Text } from "@oh-my-pi/pi-tui"; import { removeWithRetries } from "@oh-my-pi/pi-utils"; import { grepToolRenderer } from "../../src/tools/grep"; @@ -146,7 +146,6 @@ describe("tool path arrays", () => { it("search accepts a semicolon-delimited path list", async () => { const tools = await createTools(createTestSession(tempDir)); const tool = tools.find(entry => entry.name === "grep"); - expect(tool).toBeDefined(); if (!tool) throw new Error("Missing grep tool"); const result = await tool.execute("search-path-array", { @@ -168,7 +167,6 @@ describe("tool path arrays", () => { it("search accepts JSON-array string paths in direct execute", async () => { const tools = await createTools(createTestSession(tempDir)); const tool = tools.find(entry => entry.name === "grep"); - expect(tool).toBeDefined(); if (!tool) throw new Error("Missing grep tool"); const result = await tool.execute("search-json-array-string-paths", { @@ -189,7 +187,6 @@ describe("tool path arrays", () => { it("search expands delimited path entries", async () => { const tools = await createTools(createTestSession(tempDir)); const tool = tools.find(entry => entry.name === "grep"); - expect(tool).toBeDefined(); if (!tool) throw new Error("Missing grep tool"); for (const [name, entry] of [ @@ -216,7 +213,6 @@ describe("tool path arrays", () => { it("search keeps comma-delimited surviving entries when peers are missing", async () => { const tools = await createTools(createTestSession(tempDir)); const tool = tools.find(entry => entry.name === "grep"); - expect(tool).toBeDefined(); if (!tool) throw new Error("Missing grep tool"); const result = await tool.execute("search-delimited-missing", { @@ -237,7 +233,6 @@ describe("tool path arrays", () => { const session = createTestSession(tempDir); const tools = await createTools(session); const tool = tools.find(entry => entry.name === "grep"); - expect(tool).toBeDefined(); if (!tool) throw new Error("Missing grep tool"); const result = await tool.execute("search-records-snapshot", { @@ -246,7 +241,6 @@ describe("tool path arrays", () => { }); const text = getText(result); const tag = /^# apps\/\n## grep\.txt#([0-9A-F]{4})/m.exec(text)?.[1]; - expect(tag).toBeDefined(); if (!tag) throw new Error("Missing search snapshot tag"); const snapshot = session.fileSnapshotStore?.byHash( @@ -259,7 +253,6 @@ describe("tool path arrays", () => { it("search accepts a single string path through tool validation", async () => { const tools = await createTools(createTestSession(tempDir)); const tool = tools.find(entry => entry.name === "grep"); - expect(tool).toBeDefined(); if (!tool) throw new Error("Missing grep tool"); const args = validateToolArguments(tool, { @@ -312,7 +305,6 @@ describe("tool path arrays", () => { plainTheme, ); - expect(component).toBeInstanceOf(Text); expect((component as Text).getText()).toContain("in folder with spaces/"); }); it("agent hub chat renders a single-string grep path summary", async () => { diff --git a/packages/coding-agent/test/tools/irc.test.ts b/packages/coding-agent/test/tools/irc.test.ts index d4b033e8e..84075b893 100644 --- a/packages/coding-agent/test/tools/irc.test.ts +++ b/packages/coding-agent/test/tools/irc.test.ts @@ -983,7 +983,6 @@ describe("IRC", () => { expect(promptSpy).toHaveBeenCalledTimes(1); // The idle wake routes through #wakeForIrc, which batches records into one prompt — // even a lone incoming message is delivered as a one-element array. - expect(promptSpy.mock.calls[0]).toBeDefined(); const prompted = (promptSpy.mock.calls[0]![0] as unknown as CustomMessage[])[0]; expect(prompted).toMatchObject({ role: "custom", customType: "irc:incoming" }); expect(prompted.details).toMatchObject({ id: "msg-1", from: "0-Peer", message: "wake up" }); diff --git a/packages/coding-agent/test/tools/launch.test.ts b/packages/coding-agent/test/tools/launch.test.ts index 99e933646..a002b9db1 100644 --- a/packages/coding-agent/test/tools/launch.test.ts +++ b/packages/coding-agent/test/tools/launch.test.ts @@ -258,13 +258,11 @@ setInterval(() => {}, 1000); detached: false, }; const started = await first.request({ op: "start", spec, owner: "first-client" }); - expect(started.op).toBe("start"); if (started.op !== "start") throw new Error("unexpected start result"); expect(started.readyTimedOut).toBeFalse(); expect(started.daemon.state).toBe("ready"); const listed = await second.request({ op: "list" }); - expect(listed.op).toBe("list"); if (listed.op !== "list") throw new Error("unexpected list result"); expect(listed.daemons.map(daemon => daemon.name)).toEqual(["debugger"]); @@ -276,7 +274,6 @@ setInterval(() => {}, 1000); pattern: "INPUT", timeoutMs: 3_000, }); - expect(waited.op).toBe("wait"); if (waited.op !== "wait") throw new Error("unexpected wait result"); expect(waited.timedOut).toBeFalse(); expect(waited.matched).toBe("INPUT"); @@ -290,7 +287,6 @@ setInterval(() => {}, 1000); timeoutMs: 1_000, renderTerminalRows: true, } as DaemonOperation); - expect(logs.op).toBe("logs"); if (logs.op !== "logs") throw new Error("unexpected logs result"); expect(logs.text).toContain("READY"); expect(logs.text).not.toContain("\x1b"); @@ -329,7 +325,6 @@ setInterval(() => {}, 1000); expect(grepped.terminalRows).toBeUndefined(); const stopped = await first.request({ op: "stop", name: "debugger", timeoutMs: 2_000 }); - expect(stopped.op).toBe("stop"); if (stopped.op !== "stop") throw new Error("unexpected stop result"); expect(stopped.daemon.state).toBe("exited"); } finally { @@ -883,7 +878,6 @@ esac }); expect(await waitUntil(() => Bun.file(markerPath).exists(), 3_000)).toBeTrue(); - expect(await Bun.file(markerPath).text()).toBe("yes"); expect(victimError).toBeUndefined(); if (victim?.op !== "start") throw new Error("victim start result missing"); expect(victim.daemon).toMatchObject({ name: "empty-ready-victim", readyMatch: "SECOND" }); @@ -972,7 +966,6 @@ esac detached: false, }; const started = await client.request({ op: "start", spec }); - expect(started.op).toBe("start"); if (started.op !== "start") throw new Error("unexpected start result"); expect(started.readyTimedOut).toBeTrue(); expect(started.daemon.state).toBe("starting"); @@ -1014,7 +1007,6 @@ esac const t0 = Date.now(); const started = await client.request({ op: "start", spec }); const elapsed = Date.now() - t0; - expect(started.op).toBe("start"); if (started.op !== "start") throw new Error("unexpected start result"); // Woke on readyAt/terminal, not the full 60s timeout. expect(elapsed).toBeLessThan(10_000); @@ -1029,7 +1021,6 @@ esac for: "ready", timeoutMs: 60_000, }); - expect(waited.op).toBe("wait"); if (waited.op !== "wait") throw new Error("unexpected wait result"); expect(waited.timedOut).toBeFalse(); expect(waited.daemon.readyAt).toBeDefined(); @@ -1064,7 +1055,6 @@ esac const t0 = Date.now(); const started = await client.request({ op: "start", spec }); const startElapsed = Date.now() - t0; - expect(started.op).toBe("start"); if (started.op !== "start") throw new Error("unexpected start result"); expect(startElapsed).toBeLessThan(10_000); // Woke on the terminal exit rather than timing out; the readyAt marker is @@ -1084,7 +1074,6 @@ esac timeoutMs: 60_000, }); const waitElapsed = Date.now() - t1; - expect(waited.op).toBe("wait"); if (waited.op !== "wait") throw new Error("unexpected wait result"); expect(waitElapsed).toBeLessThan(10_000); expect(waited.timedOut).toBeTrue(); @@ -1119,7 +1108,6 @@ esac detached: false, }; const started = await client.request({ op: "start", spec }); - expect(started.op).toBe("start"); if (started.op !== "start") throw new Error("unexpected start result"); expect(started.daemon.readyAt).toBeDefined(); diff --git a/packages/coding-agent/test/tools/lsp-regressions.test.ts b/packages/coding-agent/test/tools/lsp-regressions.test.ts index 3153cac56..8af9e1e77 100644 --- a/packages/coding-agent/test/tools/lsp-regressions.test.ts +++ b/packages/coding-agent/test/tools/lsp-regressions.test.ts @@ -337,7 +337,6 @@ describe("lsp regressions", () => { }); const config = loadConfig(tempDir.path()); const serverConfig = getServersForFile(config, filePath)[0]?.[1]; - expect(serverConfig).toBeDefined(); if (!serverConfig) throw new Error("Custom GDScript server was not loaded"); const client = await lspClient.getOrCreateClient(serverConfig, tempDir.path(), 1_000); @@ -1373,7 +1372,6 @@ describe("lsp regressions", () => { it("sanitizes symbol metadata in renderer output", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const uiTheme = theme!; const renderOptions: RenderResultOptions = { expanded: false, isPartial: false }; @@ -1411,7 +1409,6 @@ describe("lsp regressions", () => { it("sanitizes tabs in rendered diagnostic output", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const uiTheme = theme!; const renderOptions: RenderResultOptions = { expanded: false, isPartial: false }; @@ -1435,7 +1432,6 @@ describe("lsp regressions", () => { it("sanitizes expanded generic error output (#7041)", async () => { const theme = await getThemeByName("dark"); - expect(theme).toBeDefined(); const result = renderLocalResult( { content: [{ type: "text", text: `Error:\nserver\tstderr ${"x".repeat(200)}` }], diff --git a/packages/coding-agent/test/tools/yield.test.ts b/packages/coding-agent/test/tools/yield.test.ts index 574bee40c..d18387c28 100644 --- a/packages/coding-agent/test/tools/yield.test.ts +++ b/packages/coding-agent/test/tools/yield.test.ts @@ -55,7 +55,6 @@ function makeCodexModel(): Model<"openai-codex-responses"> { describe("YieldTool", () => { it("accepts success payload with data", async () => { const tool = new YieldTool(createSession()); - expect(tool.strict).toBe(false); const result = await tool.execute("call-1", { result: { data: { ok: true } } } as never); expect(result.details).toEqual({ data: { ok: true }, status: "success", error: undefined }); }); @@ -539,7 +538,6 @@ describe("YieldTool", () => { const abortResult = await tool.execute("call-empty-abort", { result: {} } as never); const details = abortResult.details; - expect(details).toBeDefined(); if (!details) throw new Error("missing abort details"); expect(details.status).toBe("aborted"); expect(details.data).toBeUndefined(); @@ -569,7 +567,6 @@ describe("YieldTool", () => { const abortResult = await tool.execute("call-empty-after-reset-abort", { result: {} } as never); const details = abortResult.details; - expect(details).toBeDefined(); if (!details) throw new Error("missing abort details"); expect(details.status).toBe("aborted"); expect(details.data).toBeUndefined(); @@ -809,6 +806,7 @@ describe("YieldTool", () => { }, }), ); + expect(tool.strict).toBe(true); const toolDefinition: Tool = { @@ -817,6 +815,7 @@ describe("YieldTool", () => { parameters: tool.parameters, strict: tool.strict, }; + // One incremental finding (a single element, not the full output) must validate. expect( validateToolArguments(toolDefinition, { @@ -1183,10 +1182,6 @@ describe("YieldTool", () => { 'Submit success as {"result":{"data":}} or failure as {"result":{"error":"message"}}.', ); }); - it("sets lenientArgValidation so agent-loop bypasses validation errors", () => { - const tool = new YieldTool(createSession()); - expect(tool.lenientArgValidation).toBe(true); - }); it("falls back to loose schema when outputSchema contains unresolved external $ref", async () => { const tool = new YieldTool( createSession({ diff --git a/packages/snapcompact/test/snapcompact.test.ts b/packages/snapcompact/test/snapcompact.test.ts index 8d975ad1a..9285dd5ac 100644 --- a/packages/snapcompact/test/snapcompact.test.ts +++ b/packages/snapcompact/test/snapcompact.test.ts @@ -383,7 +383,6 @@ describe("shape resolution", () => { }); it("every catalog variant resolves to a complete, renderable shape", () => { - expect(snapcompact.SHAPE_VARIANT_NAMES.length).toBeGreaterThan(0); for (const name of snapcompact.SHAPE_VARIANT_NAMES) { expect(snapcompact.isShapeVariantName(name)).toBe(true); expect(snapcompact.isShape(snapcompact.resolveShape({ api: "openai-responses" }, name))).toBe(true); @@ -604,7 +603,6 @@ describe("renderMany", () => { expect(short).toHaveLength(1); expect(short[0].type).toBe("image"); expect(short[0].mimeType).toBe("image/png"); - expect(short[0].data.length).toBeGreaterThan(0); const text = "x".repeat(capacity * 2 + 10); const frames = await snapcompact.renderMany(text, { shape, frameSize: TEST_FRAME_SIZE }); @@ -872,8 +870,6 @@ describe("compact", () => { fileOps.edited.add("src/login.ts"); const result = await snapcompact.compact(makePreparation({ fileOps }), { frameSize: TEST_FRAME_SIZE }); - expect(result.firstKeptEntryId).toBe("kept-1"); - expect(result.tokensBefore).toBe(99000); expect(result.summary).toContain("HISTORY"); expect(result.summary).toContain("`¶user:`"); expect(result.summary).toContain("`¶call:`"); @@ -881,9 +877,7 @@ describe("compact", () => { expect(result.summary).toContain("FILES\n===================\n# src/\nauth.ts (Read)\nlogin.ts (Write)"); const archive = snapcompact.getPreservedArchive(result.preserveData); - expect(archive).toBeDefined(); expect(archive?.frames).toHaveLength(0); - expect(archive?.textHead).toBeTruthy(); expect(archive?.textTail).toBeUndefined(); expect(archive?.truncatedChars).toBe(0); @@ -961,7 +955,6 @@ describe("compact", () => { { shape: silver, frameSize: 64, maxFrames: 1 }, ); const archive = snapcompact.getPreservedArchive(result.preserveData); - expect(archive).toBeDefined(); expect(archive?.frames.length).toBeGreaterThan(0); expect(archive?.frames.every(frame => frame.font === "silver")).toBe(true); }); @@ -1311,19 +1304,6 @@ describe("new shape variants", () => { } }); - it("carries the eval-winning capability flags", () => { - expect(snapcompact.SHAPE_VARIANTS["6x12-dim"]).toMatchObject({ font: "6x12", stopwordDim: true }); - expect(snapcompact.SHAPE_VARIANTS["8x13-bw"]).toMatchObject({ font: "8x13", cellHeight: 13 }); - expect(snapcompact.SHAPE_VARIANTS["8on16-bw"]).toMatchObject({ font: "8x13", cellHeight: 16, stretch: false }); - expect(snapcompact.SHAPE_VARIANTS["doc-8on16-bw"].columns).toBe(2); - expect(snapcompact.SHAPE_VARIANTS["doc-8on16-sent"].variant).toBe("sent"); - expect(snapcompact.SHAPE_VARIANTS["doc-8on16-sent-dim"]).toMatchObject({ - columns: 2, - stopwordDim: true, - variant: "sent", - }); - }); - it("isShape validates the new optional fields", () => { const base = snapcompact.resolveShape(undefined, "doc-8on16-sent-dim"); expect(snapcompact.isShape({ ...base, columns: 3 })).toBe(false); diff --git a/packages/tui/test/autocomplete.test.ts b/packages/tui/test/autocomplete.test.ts index 472e26dac..99f8550c7 100644 --- a/packages/tui/test/autocomplete.test.ts +++ b/packages/tui/test/autocomplete.test.ts @@ -14,10 +14,7 @@ describe("CombinedAutocompleteProvider", () => { const result = await provider.getForceFileSuggestions(lines, cursorLine, cursorCol); - expect(result).not.toBeNull(); - if (result) { - expect(result.prefix).toBe("/"); - } + expect(result?.prefix).toBe("/"); }); it("extracts /A from '/A' when forced", async () => { @@ -54,10 +51,7 @@ describe("CombinedAutocompleteProvider", () => { const result = await provider.getForceFileSuggestions(lines, cursorLine, cursorCol); - expect(result).not.toBeNull(); - if (result) { - expect(result.prefix).toBe("/"); - } + expect(result?.prefix).toBe("/"); }); }); @@ -117,7 +111,6 @@ describe("CombinedAutocompleteProvider", () => { const result = await provider.getSuggestions([line], 0, line.length); - expect(result).not.toBeNull(); expect(result?.prefix).toBe("/tmp"); expect(result?.items.map(item => item.value)).toContain("/tmp/"); }, @@ -381,9 +374,7 @@ describe("CombinedAutocompleteProvider", () => { const result = await provider.getSuggestions([line], 0, line.length); - expect(result).not.toBeNull(); expect(result?.prefix).toBe("C:/"); - expect(result?.items.length).toBeGreaterThan(0); if (process.platform !== "win32") { expect(result?.items.map(item => item.value)).toContain("C:/alpha.ts"); } @@ -588,7 +579,6 @@ describe("CombinedAutocompleteProvider", () => { const line = "@controller"; const result = await provider.getSuggestions([line], 0, line.length); - expect(result).not.toBeNull(); const values = result?.items.map(item => item.value) ?? []; expect(values.length).toBeGreaterThan(20); expect(values.length).toBeGreaterThanOrEqual(total); @@ -701,7 +691,6 @@ describe("CombinedAutocompleteProvider", () => { const provider = new CombinedAutocompleteProvider([], baseDir); const line = "./up"; const result = await provider.getForceFileSuggestions([line], 0, line.length); - expect(result).not.toBeNull(); const values = result?.items.map(item => item.value) ?? []; expect(values).toContain("./update.sh"); }); @@ -712,7 +701,6 @@ describe("CombinedAutocompleteProvider", () => { const provider = new CombinedAutocompleteProvider([], baseDir); const line = "./sr"; const result = await provider.getForceFileSuggestions([line], 0, line.length); - expect(result).not.toBeNull(); const values = result?.items.map(item => item.value) ?? []; expect(values).toContain("./src/"); }); @@ -749,7 +737,6 @@ describe("trySyncSlashCompletion", () => { "/tmp", ); const result = provider.trySyncSlashCompletion("/mo"); - expect(result).not.toBeNull(); expect(result!.prefix).toBe("/mo"); expect(result!.items.map(i => i.value)).toEqual(["model"]); }); @@ -760,12 +747,11 @@ describe("trySyncSlashCompletion", () => { "/tmp", ); const result = provider.trySyncSlashCompletion(" /mo"); - expect(result).not.toBeNull(); expect(result!.prefix).toBe(" /mo"); expect(result!.items.map(i => i.value)).toEqual(["model"]); }); - it("matches multiple commands and sorts by relevance", () => { + it("matches multiple commands and excludes non-matches", () => { const provider = new CombinedAutocompleteProvider( [ { name: "model", description: "Switch AI model", value: "model" }, @@ -775,19 +761,11 @@ describe("trySyncSlashCompletion", () => { "/tmp", ); const result = provider.trySyncSlashCompletion("/mo"); - expect(result).not.toBeNull(); const values = result!.items.map(i => i.value); // /model and /mode should match; /help should not expect(values).toContain("model"); expect(values).toContain("mode"); expect(values).not.toContain("help"); - // The better name match should come first (higher score) - const modelIdx = values.indexOf("model"); - const modeIdx = values.indexOf("mode"); - // model matches 3/5 chars, mode matches 3/4 chars — mode has higher match ratio - // Both should be present; order depends on fuzzyScore internals - expect(modelIdx).not.toBe(-1); - expect(modeIdx).not.toBe(-1); }); it("matches case-insensitively", () => { @@ -796,7 +774,6 @@ describe("trySyncSlashCompletion", () => { "/tmp", ); const result = provider.trySyncSlashCompletion("/MOD"); - expect(result).not.toBeNull(); expect(result!.items.map(i => i.value)).toContain("Model"); }); @@ -806,7 +783,6 @@ describe("trySyncSlashCompletion", () => { "/tmp", ); const result = provider.trySyncSlashCompletion("/model"); - expect(result).not.toBeNull(); expect(result!.items.map(i => i.value)).toContain("md"); }); @@ -844,7 +820,6 @@ describe("trySyncSlashCompletion", () => { it("handles AutocompleteItem-shaped commands (no 'name' property)", () => { const provider = new CombinedAutocompleteProvider([{ value: "model", label: "Switch model" }], "/tmp"); const result = provider.trySyncSlashCompletion("/mod"); - expect(result).not.toBeNull(); expect(result!.items.map(i => i.value)).toEqual(["model"]); }); @@ -857,7 +832,6 @@ describe("trySyncSlashCompletion", () => { "/tmp", ); const result = await provider.getSuggestions(["/"], 0, 1); - expect(result).not.toBeNull(); expect(result!.items.map(i => i.value)).toEqual(["setup", "usage"]); }); @@ -867,7 +841,6 @@ describe("trySyncSlashCompletion", () => { "/tmp", ); const result = await provider.getSuggestions(["/mod"], 0, 4); - expect(result).not.toBeNull(); expect(result!.items.map(i => i.value)).toEqual(["model"]); }); @@ -880,7 +853,6 @@ describe("trySyncSlashCompletion", () => { "/tmp", ); const result = provider.trySyncSlashCompletion("/set"); - expect(result).not.toBeNull(); // The sync-completion path applies items[0] on Enter; the shorter `setup` // must not jump ahead of the earlier-registered `settings`. expect(result!.items[0]?.value).toBe("settings"); @@ -895,7 +867,6 @@ describe("trySyncSlashCompletion", () => { "/tmp", ); const result = provider.trySyncSlashCompletion("/providers"); - expect(result).not.toBeNull(); expect(result!.items[0]?.value).toBe("providers"); }); @@ -908,7 +879,6 @@ describe("trySyncSlashCompletion", () => { "/tmp", ); const result = provider.trySyncSlashCompletion("/q"); - expect(result).not.toBeNull(); // The sync-completion path applies items[0] on Enter. Even though `queue` // is registered first and shares the `q` prefix, the exact `q` alias on // `quit` must win (score 1000 > 900) so /q + Enter dispatches the `q` diff --git a/packages/tui/test/image-budget.test.ts b/packages/tui/test/image-budget.test.ts index 4717c926e..2792f7e72 100644 --- a/packages/tui/test/image-budget.test.ts +++ b/packages/tui/test/image-budget.test.ts @@ -54,10 +54,6 @@ function pass(budget: ImageBudget, count: number): { suppressed: boolean[]; rese } describe("ImageBudget", () => { - it("defaults to eight live images", () => { - expect(new ImageBudget().cap).toBe(8); - }); - it("keeps every image live while at or under the cap", () => { const budget = new ImageBudget(3, () => {}); const first = pass(budget, 2); diff --git a/packages/tui/test/issue-2088-repro.test.ts b/packages/tui/test/issue-2088-repro.test.ts index a8cfe72c4..e93eb63f0 100644 --- a/packages/tui/test/issue-2088-repro.test.ts +++ b/packages/tui/test/issue-2088-repro.test.ts @@ -2470,7 +2470,6 @@ describe("multiplexer detection gates ED3 on resize", () => { await Bun.sleep(DEBOUNCE_SETTLE_WAIT_MS); await settle(term); const out = writes.join(""); - expect(out.length).toBeGreaterThan(0); expect(out).not.toContain(ED3); expect(tui.fullRedraws - baselineRedraws).toBe(1); expect(visible(term)).toEqual(Array.from({ length: 10 }, (_v, i) => `line-${i + 10}`)); @@ -2503,7 +2502,6 @@ describe("multiplexer detection gates ED3 on resize", () => { await Bun.sleep(DEBOUNCE_SETTLE_WAIT_MS); await settle(term); const out = writes.join(""); - expect(out.length).toBeGreaterThan(0); expect(out).not.toContain(ED3); expect(tui.fullRedraws - baselineRedraws).toBe(1); expect(visible(term)).toEqual(Array.from({ length: 10 }, (_v, i) => `line-${i + 10}`)); diff --git a/packages/tui/test/markdown.test.ts b/packages/tui/test/markdown.test.ts index 1c1d821fe..f4d099f77 100644 --- a/packages/tui/test/markdown.test.ts +++ b/packages/tui/test/markdown.test.ts @@ -68,9 +68,6 @@ describe("Markdown component", () => { const lines = markdown.render(80); - // Check that we have content - expect(lines.length > 0).toBeTruthy(); - // Strip ANSI codes for checking const plainLines = lines.map(line => stripVTControlCharacters(line)); @@ -338,9 +335,6 @@ describe("Markdown component", () => { const lines = markdown.render(80); - // Should render without errors - expect(lines.length > 0).toBeTruthy(); - const plainLines = lines.map(line => stripVTControlCharacters(line)); expect(plainLines.some(line => line.includes("Very long column header"))).toBeTruthy(); expect(plainLines.some(line => line.includes("This is a much longer cell content"))).toBeTruthy(); @@ -423,7 +417,6 @@ describe("Markdown component", () => { // Borders should stay intact (exactly 2 vertical borders for a 1-col table) const tableLines = plainLines.filter(line => line.startsWith("|")); - expect(tableLines.length > 0, "Expected table rows to render").toBeTruthy(); for (const line of tableLines) { const borderCount = line.split("|").length - 1; expect(borderCount, `Expected 2 borders, got ${borderCount}: "${line}"`).toBe(2); @@ -530,9 +523,6 @@ describe("Markdown component", () => { const lines = markdown.render(15); const plainLines = lines.map(line => stripVTControlCharacters(line).trimEnd()); - // Should not crash and should produce output - expect(lines.length > 0, "Should produce output").toBeTruthy(); - // Lines should not exceed width for (const line of plainLines) { expect(line.length <= 15, `Line exceeds width 15: "${line}" (length: ${line.length})`).toBeTruthy(); diff --git a/packages/tui/test/render-regressions.test.ts b/packages/tui/test/render-regressions.test.ts index 7df42f9d2..59fac77ee 100644 --- a/packages/tui/test/render-regressions.test.ts +++ b/packages/tui/test/render-regressions.test.ts @@ -1429,7 +1429,6 @@ describe("TUI terminal-state regressions", () => { await settle(term); const paint = writes.find(write => write.includes("\x1b[3J")); - expect(paint).toBeDefined(); expect(paint).toContain("\x1b[?2026h"); expect(paint).toContain("\x1b[?2026l"); expect(visible(term)).toEqual(["resumed-5", "resumed-6", "resumed-7"]);